Files
recipe-app/frontend/app/recipes/import/ImportFilePage.tsx
T
Nils-Johan Gynther 4f183df711 feat: Implement quick import feature for recipes
- Added QuickImportController and QuickImportService to handle recipe imports from URLs and file paths.
- Created QuickImportModule to encapsulate the quick import functionality.
- Developed frontend ImportFilePage for users to upload files or enter URLs for recipe import.
- Integrated API proxy to communicate with the backend for quick import requests.
- Implemented WriteRecipePage for users to manually input recipes with Markdown support.
- Added page routing for the new import and write recipe functionalities.
2026-04-12 07:41:18 +02:00

277 lines
9.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import Link from 'next/link';
import { useState } from 'react';
import Navigation from '../../Navigation';
export default function ImportFilePage() {
const [selectedMethod, setSelectedMethod] = useState<'file' | 'url' | null>(null);
const [uploadProgress, setUploadProgress] = useState(0);
const [error, setError] = useState<string | null>(null);
const handleFileUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
setError(null);
setUploadProgress(0);
// Placeholder för filuppladdning
// I framtiden kan detta hanteras med backend-endpoint för PDF-parsing
if (file.type === 'application/pdf') {
setError('PDF-import är under utveckling. Använd "Skriv in recept" för att mata in recept manuellt.');
} else {
setError('Endast PDF-filer stöds för närvarande.');
}
setUploadProgress(0);
};
const handleURLSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const url = formData.get('url') as string;
if (!url) {
setError('Vänligen ange en URL');
return;
}
setError('Länk-import är under utveckling. Använd "Skriv in recept" för att mata in recept manuellt.');
};
return (
<main style={{ padding: '1rem', maxWidth: '900px', margin: '0 auto' }}>
<Navigation />
<h1 style={{ marginBottom: '0.5rem' }}>Importera från fil eller länk</h1>
<p style={{ color: '#666', marginBottom: '1.5rem' }}>
Ladda upp en receptfil (PDF) eller ange en URL för att importera ett recept.
</p>
{error && (
<div
style={{
background: '#fef2f2',
border: '1px solid #fca5a5',
borderRadius: '6px',
padding: '1rem',
marginBottom: '1.5rem',
color: '#dc2626',
fontSize: '0.95rem',
}}
>
{error}
</div>
)}
<div
style={{
display: 'grid',
gridTemplateColumns: '1fr 1fr',
gap: '1.5rem',
marginBottom: '2rem',
}}
>
{/* Fil-upload */}
<div
onClick={() => setSelectedMethod('file')}
style={{
padding: '2rem',
border: selectedMethod === 'file' ? '2px solid #0070f3' : '2px solid #e5e7eb',
borderRadius: '8px',
background: selectedMethod === 'file' ? '#f0f9ff' : '#f9fafb',
cursor: 'pointer',
transition: 'all 0.2s',
}}
>
<h2 style={{ margin: '0 0 1rem 0', fontSize: '1.2rem', color: '#0070f3' }}>
📄 Ladda upp fil
</h2>
<p style={{ color: '#666', margin: '0 0 1rem 0', fontSize: '0.95rem' }}>
Ladda upp ett recept från en PDF eller textfil
</p>
{selectedMethod === 'file' && (
<div style={{ marginTop: '1rem' }}>
<label
style={{
display: 'block',
padding: '1rem',
background: 'white',
border: '2px dashed #0070f3',
borderRadius: '6px',
textAlign: 'center',
cursor: 'pointer',
transition: 'all 0.2s',
}}
onDragOver={(e) => {
e.preventDefault();
(e.currentTarget as HTMLElement).style.background = '#e3f2fd';
}}
onDragLeave={(e) => {
(e.currentTarget as HTMLElement).style.background = 'white';
}}
>
<input
type="file"
accept=".pdf,.txt,.docx"
onChange={handleFileUpload}
style={{ display: 'none' }}
/>
<p style={{ margin: '0', color: '#0070f3', fontWeight: 600 }}>
Dra och släpp fil här
</p>
<p style={{ margin: '0.5rem 0 0 0', color: '#999', fontSize: '0.85rem' }}>
eller klicka för att välja
</p>
<p style={{ margin: '0.5rem 0 0 0', color: '#999', fontSize: '0.8rem' }}>
PDF, TXT, DOCX stöds
</p>
</label>
{uploadProgress > 0 && uploadProgress < 100 && (
<div style={{ marginTop: '0.75rem' }}>
<div
style={{
width: '100%',
height: '6px',
background: '#e5e7eb',
borderRadius: '3px',
overflow: 'hidden',
}}
>
<div
style={{
height: '100%',
background: '#0070f3',
width: `${uploadProgress}%`,
transition: 'width 0.3s',
}}
/>
</div>
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.85rem', color: '#666' }}>
{uploadProgress}%
</p>
</div>
)}
</div>
)}
</div>
{/* URL-import */}
<div
onClick={() => setSelectedMethod('url')}
style={{
padding: '2rem',
border: selectedMethod === 'url' ? '2px solid #10b981' : '2px solid #e5e7eb',
borderRadius: '8px',
background: selectedMethod === 'url' ? '#f0fdf4' : '#f9fafb',
cursor: 'pointer',
transition: 'all 0.2s',
}}
>
<h2 style={{ margin: '0 0 1rem 0', fontSize: '1.2rem', color: '#10b981' }}>
🔗 Länk till recept
</h2>
<p style={{ color: '#666', margin: '0 0 1rem 0', fontSize: '0.95rem' }}>
Ange URL till en receptsida eller blogg
</p>
{selectedMethod === 'url' && (
<form onSubmit={handleURLSubmit} style={{ marginTop: '1rem' }}>
<input
type="url"
name="url"
placeholder="https://exempel.se/recept/..."
style={{
width: '100%',
padding: '0.75rem',
border: '1px solid #d1d5db',
borderRadius: '6px',
fontSize: '0.9rem',
boxSizing: 'border-box',
marginBottom: '0.75rem',
}}
/>
<button
type="submit"
style={{
width: '100%',
padding: '0.75rem',
background: '#10b981',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontWeight: 500,
fontSize: '0.95rem',
}}
>
Importera från länk
</button>
</form>
)}
</div>
</div>
{/* Info-box */}
<div
style={{
background: '#fef3c7',
border: '1px solid #fcd34d',
borderRadius: '6px',
padding: '1rem',
marginBottom: '1.5rem',
color: '#92400e',
fontSize: '0.9rem',
}}
>
<strong>💡 Tips:</strong> För närvarande är PDF och länk-import under utveckling. Du kan{' '}
<Link
href="/recipes/write"
style={{ color: '#0070f3', textDecoration: 'none', fontWeight: 600 }}
>
skriv in receptet manuellt
</Link>{' '}
eller prova att ladda upp en fil och se om det fungerar.
</div>
{/* Knapp för att gå tillbaka */}
<div style={{ display: 'flex', gap: '1rem' }}>
<Link
href="/recipes/create"
style={{
padding: '0.75rem 1.5rem',
background: 'transparent',
border: '1px solid #ddd',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '1rem',
textDecoration: 'none',
color: '#333',
fontWeight: 500,
}}
>
Tillbaka
</Link>
<Link
href="/recipes/write"
style={{
padding: '0.75rem 1.5rem',
background: '#0070f3',
color: 'white',
border: 'none',
borderRadius: '4px',
textDecoration: 'none',
cursor: 'pointer',
fontSize: '1rem',
fontWeight: 500,
}}
>
Skriv in recept istället
</Link>
</div>
</main>
);
}