Files
archived-form/src/app/mes-formulaires/page.tsx
T
Puechberty Arthur 1611ad7440 add form site
2026-03-02 13:38:13 +01:00

195 lines
9.7 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import Link from "next/link"
import { getMyForms, removeForm, LocalStorageForm } from "@/lib/localStorage"
export default function MyFormsPage() {
const [forms, setForms] = useState<LocalStorageForm[]>([])
const [loading, setLoading] = useState(true)
const [deleteConfirm, setDeleteConfirm] = useState<string | null>(null)
const [deleting, setDeleting] = useState(false)
useEffect(() => {
setForms(getMyForms())
setLoading(false)
}, [])
const handleDelete = async (publicId: string, secretKey: string) => {
setDeleting(true)
try {
const response = await fetch(`/api/forms/${publicId}?secret=${secretKey}`, {
method: "DELETE",
})
if (response.ok) {
removeForm(publicId)
setForms(getMyForms())
}
} catch (error) {
console.error("Error deleting form:", error)
} finally {
setDeleting(false)
setDeleteConfirm(null)
}
}
const copyLink = async (publicId: string) => {
const url = `${window.location.origin}/formulaire/${publicId}`
await navigator.clipboard.writeText(url)
}
if (loading) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
</div>
)
}
return (
<div className="min-h-screen bg-gray-50 py-8">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6 sm:mb-8">
<div>
<h1 className="text-2xl sm:text-3xl font-bold text-gray-900">Mes formulaires</h1>
<p className="mt-1 sm:mt-2 text-sm sm:text-base text-gray-600">
Retrouvez tous vos formulaires créés sur cet appareil.
</p>
</div>
<Link
href="/creer"
className="w-full sm:w-auto px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center justify-center font-medium"
>
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
</svg>
Nouveau formulaire
</Link>
</div>
{forms.length === 0 ? (
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6 sm:p-12 text-center">
<div className="w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-6">
<svg className="w-10 h-10 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</div>
<h2 className="text-xl font-semibold text-gray-900 mb-2">Aucun formulaire</h2>
<p className="text-gray-600 mb-6">
Vous n&apos;avez pas encore créé de formulaire sur cet appareil.
</p>
<Link
href="/creer"
className="inline-flex items-center px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
</svg>
Créer mon premier formulaire
</Link>
</div>
) : (
<div className="space-y-4">
{forms.map((form) => (
<div
key={form.publicId}
className="bg-white rounded-xl shadow-sm border border-gray-200 p-6"
>
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
<div className="flex-1">
<h2 className="text-lg font-semibold text-gray-900">{form.title}</h2>
<p className="text-sm text-gray-500 mt-1">
Créé le {new Date(form.createdAt).toLocaleDateString("fr-FR", {
day: "numeric",
month: "long",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
})}
</p>
</div>
<div className="flex flex-wrap gap-2">
<button
onClick={() => copyLink(form.publicId)}
className="px-3 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors flex items-center text-sm font-medium"
>
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z" />
</svg>
Partager
</button>
<Link
href={`/formulaire/${form.publicId}`}
className="px-3 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors flex items-center text-sm font-medium"
>
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
Voir
</Link>
<Link
href={`/formulaire/${form.publicId}/resultats?secret=${form.secretKey}`}
className="px-3 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center text-sm font-medium"
>
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
Résultats
</Link>
{deleteConfirm === form.publicId ? (
<div className="flex items-center gap-2">
<button
onClick={() => handleDelete(form.publicId, form.secretKey)}
disabled={deleting}
className="px-3 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors text-sm font-medium disabled:opacity-50"
>
{deleting ? "..." : "Confirmer"}
</button>
<button
onClick={() => setDeleteConfirm(null)}
className="px-3 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors text-sm font-medium"
>
Annuler
</button>
</div>
) : (
<button
onClick={() => setDeleteConfirm(form.publicId)}
className="px-3 py-2 bg-red-100 text-red-700 rounded-lg hover:bg-red-200 transition-colors flex items-center text-sm font-medium"
>
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
Supprimer
</button>
)}
</div>
</div>
</div>
))}
</div>
)}
{/* Information */}
<div className="mt-8 bg-blue-50 border border-blue-100 rounded-xl p-6">
<div className="flex items-start space-x-3">
<svg className="w-6 h-6 text-blue-600 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<h3 className="font-medium text-blue-900">Information importante</h3>
<p className="text-sm text-blue-700 mt-1">
Vos formulaires sont sauvegardés localement sur cet appareil.
Si vous effacez les données de votre navigateur ou changez d&apos;appareil,
vous perdrez l&apos;accès aux résultats. Pensez à sauvegarder les liens d&apos;administration.
</p>
</div>
</div>
</div>
</div>
</div>
)
}