feat: add localStorage draft persistence to form filler and introduce reusable SimpleTooltip component

This commit is contained in:
2026-05-28 18:04:41 +07:00 Unverified
parent 9879fd8ee8
commit 5abf0477c0
2 changed files with 65 additions and 10 deletions
+34 -10
View File
@@ -1,6 +1,6 @@
"use client";
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
@@ -67,23 +67,50 @@ interface FormFillerClientProps {
initialAnswers?: Record<string, string>;
}
const LS_KEY = (formId: string) => `form-draft-${formId}`;
export function FormFillerClient({ form, questions, initialAnswers = {} }: FormFillerClientProps) {
const router = useRouter();
// Pre-process checkbox answers since they are stored as comma-separated strings
// Merge: server answers take precedence over localStorage draft
const getInitialState = () => {
const serverAnswers = { ...initialAnswers };
let draft: Record<string, string> = {};
try {
const raw = localStorage.getItem(LS_KEY(form.id));
if (raw) draft = JSON.parse(raw);
} catch {}
// Merge draft under server values
return { ...draft, ...serverAnswers };
};
const merged = getInitialState();
// Pre-process checkbox answers
const initialCheckboxes: Record<string, string[]> = {};
for (const q of questions) {
if (q.type === "checkbox" && initialAnswers[q.id]) {
initialCheckboxes[q.id] = initialAnswers[q.id].split(", ");
if (q.type === "checkbox" && merged[q.id]) {
initialCheckboxes[q.id] = merged[q.id].split(", ");
}
}
const [answers, setAnswers] = useState<Record<string, string>>(initialAnswers);
const [answers, setAnswers] = useState<Record<string, string>>(merged);
const [checkboxAnswers, setCheckboxAnswers] = useState<Record<string, string[]>>(initialCheckboxes);
const [submitting, setSubmitting] = useState(false);
const isUpdating = Object.keys(initialAnswers).length > 0;
// Persist to localStorage whenever answers change
useEffect(() => {
try {
const combined: Record<string, string> = { ...answers };
for (const [qId, opts] of Object.entries(checkboxAnswers)) {
combined[qId] = opts.join(", ");
}
localStorage.setItem(LS_KEY(form.id), JSON.stringify(combined));
} catch {}
}, [answers, checkboxAnswers, form.id]);
const handleTextChange = (questionId: string, value: string) => {
setAnswers((prev) => ({ ...prev, [questionId]: value }));
};
@@ -144,10 +171,7 @@ export function FormFillerClient({ form, questions, initialAnswers = {} }: FormF
const res = await submitForm(form.id, formattedAnswers);
if (res.ok) {
toast.success(isUpdating ? "Form updated successfully!" : "Form submitted successfully!");
if (!isUpdating) {
setAnswers({});
setCheckboxAnswers({});
}
// Fields are kept as-is; localStorage already reflects current state
}
} catch (err: any) {
console.error(err);