import { useSignal } from '@preact/signals'; import { useEffect } from 'preact/hooks'; import { DashboardLink } from '/lib/types.ts'; import { validateUrl } from '/lib/utils/misc.ts'; import { RequestBody, ResponseBody } from '/routes/api/dashboard/save-links.tsx'; interface LinksProps { initialLinks: DashboardLink[]; } export default function Links({ initialLinks }: LinksProps) { const hasSavedTimeout = useSignal>(0); const isSaving = useSignal(false); const hasSaved = useSignal(false); const links = useSignal(initialLinks); async function saveLinks(newLinks: DashboardLink[]) { if (isSaving.value) { return; } hasSaved.value = false; isSaving.value = true; const oldLinks = [...links.value]; links.value = newLinks; try { const requestBody: RequestBody = { links: newLinks }; const response = await fetch(`/api/dashboard/save-links`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as ResponseBody; if (!result.success) { throw new Error('Failed to save notes!'); } } catch (error) { console.error(error); links.value = [...oldLinks]; } isSaving.value = false; hasSaved.value = true; if (hasSavedTimeout.value) { clearTimeout(hasSavedTimeout.value); } hasSavedTimeout.value = setTimeout(() => { hasSaved.value = false; }, 3000); } useEffect(() => { return () => { if (hasSavedTimeout.value) { clearTimeout(hasSavedTimeout.value); } }; }); function onClickAddLink() { const name = (prompt(`What's the **name** for the new link?`) || '').trim(); const url = (prompt(`What's the **URL** for the new link?`) || '').trim(); if (!name || !url) { alert('A name and URL are required for a new link!'); return; } if (!validateUrl(url)) { alert('Invalid URL!'); return; } const newLinks = [...links.value, { name, url }]; saveLinks(newLinks); } function onClickDeleteLink(indexToDelete: number) { if (confirm('Are you sure you want to delete this link?')) { const newLinks = [...links.value]; newLinks.splice(indexToDelete, 1); saveLinks(newLinks); } } function onClickMoveLeftLink(indexToMoveLeft: number) { if (indexToMoveLeft <= 0) { return; } if (confirm('Are you sure you want to move this link left?')) { const newLinks = [...links.value]; const linkToMove = newLinks.splice(indexToMoveLeft, 1); newLinks.splice(indexToMoveLeft - 1, 0, linkToMove[0]); saveLinks(newLinks); } } return ( <>
{links.value.map((link, index) => (
{index > 0 ? ( ) : null}
))}
{isSaving.value ? ( <> Saving... ) : null} {hasSaved.value ? ( <> Saved! ) : null} {!isSaving.value && !hasSaved.value ? <>  : null}
); }