feat: add localStorage draft persistence to form filler and introduce reusable SimpleTooltip component
This commit is contained in:
+34
-10
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user