phase 3 - ical import/export
This commit is contained in:
@@ -8,6 +8,7 @@ import { Input } from '@/components/ui/input'
|
||||
import { type CalendarEvent } from '@/lib/types'
|
||||
|
||||
import { addEvent, deleteEvent, getAllEvents, clearEvents } from '@/lib/db'
|
||||
import { parseICS, generateICS } from '@/lib/ical'
|
||||
|
||||
export default function HomePage() {
|
||||
const [events, setEvents] = useState<CalendarEvent[]>([])
|
||||
@@ -15,7 +16,6 @@ export default function HomePage() {
|
||||
const [title, setTitle] = useState('')
|
||||
const [start, setStart] = useState('')
|
||||
|
||||
// Load events only in the browser
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const stored = await getAllEvents()
|
||||
@@ -42,11 +42,61 @@ export default function HomePage() {
|
||||
setEvents([])
|
||||
}
|
||||
|
||||
// --- IMPORT ---
|
||||
const handleImport = async (file: File) => {
|
||||
const text = await file.text()
|
||||
const parsed = parseICS(text)
|
||||
|
||||
// Save to DB and update state
|
||||
for (const ev of parsed) {
|
||||
await addEvent(ev)
|
||||
}
|
||||
const stored = await getAllEvents()
|
||||
setEvents(stored)
|
||||
}
|
||||
|
||||
// --- EXPORT ---
|
||||
const handleExport = () => {
|
||||
const icsData = generateICS(events)
|
||||
const blob = new Blob([icsData], { type: 'text/calendar' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = 'events.ics'
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-2">
|
||||
<div className="space-y-4">
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button onClick={() => setOpen(true)}>Add Event</Button>
|
||||
{events.length > 0 && <Button variant="destructive" onClick={handleClearAll}>Clear All</Button>}
|
||||
{events.length > 0 && (
|
||||
<>
|
||||
<Button variant="secondary" onClick={handleExport}>
|
||||
Export .ics
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={handleClearAll}>
|
||||
Clear All
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<label className="cursor-pointer">
|
||||
<span className="px-3 py-2 bg-blue-500 text-white rounded">Import .ics</span>
|
||||
<input
|
||||
type="file"
|
||||
accept=".ics"
|
||||
hidden
|
||||
onChange={e => {
|
||||
if (e.target.files?.length) {
|
||||
handleImport(e.target.files[0])
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<ul className="mt-4 space-y-2">
|
||||
|
||||
Reference in New Issue
Block a user