diff --git a/app/form/admin/client.tsx b/app/form/admin/client.tsx index 71452bd..41c32cb 100644 --- a/app/form/admin/client.tsx +++ b/app/form/admin/client.tsx @@ -21,7 +21,7 @@ import { } from "@/app/actions/questions"; import { Plus, Trash, ArrowUp, ArrowDown, Loader2, Save, Image as ImageIcon, X } from "lucide-react"; import Image from 'next/image'; -import { RichTextEditor } from "@/components/ui/rich-text-editor"; +import { RichTextEditor } from "@/components/rich-text-editor"; interface Question { id: string; diff --git a/app/form/admin/result/[id]/client.tsx b/app/form/admin/result/[id]/client.tsx index e686a88..7e8c1d9 100644 --- a/app/form/admin/result/[id]/client.tsx +++ b/app/form/admin/result/[id]/client.tsx @@ -16,6 +16,8 @@ import { import { Copy, Check, Users, Calendar, Clock } from "lucide-react"; import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; import Image from 'next/image'; +import { stripHtml } from "@/lib/utils"; +import { HtmlDisplay } from "@/components/html-display"; interface Question { id: string; @@ -112,9 +114,9 @@ export default function SubmissionDetailClient({ >
- +
+ +
{wasEdited && (

edited @@ -173,7 +175,7 @@ export default function SubmissionDetailClient({ History - {q.label} + {stripHtml(q.label)} diff --git a/app/form/client.tsx b/app/form/client.tsx index 960b8d3..deda920 100644 --- a/app/form/client.tsx +++ b/app/form/client.tsx @@ -9,6 +9,9 @@ import { Textarea } from "@/components/ui/textarea"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Checkbox } from "@/components/ui/checkbox"; import { Label } from "@/components/ui/label"; +import { cn, stripHtml } from "@/lib/utils"; +import { HtmlDisplay } from "@/components/html-display"; +import { FormattedText } from "@/components/formatted-text"; import { Dialog, DialogContent, DialogTrigger, DialogTitle } from "@/components/ui/dialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"; import { toast } from "sonner"; @@ -28,40 +31,7 @@ import { FormMessage, } from "@/components/ui/form"; -function FormattedText({ text }: { text: string }) { - const lines = text.split('\n'); - const urlRegex = /(https?:\/\/[^\s]+)/g; - return ( - <> - {lines.map((line, i) => { - const parts = line.split(urlRegex); - return ( - - {i > 0 &&
} - {parts.map((part, j) => { - if (part.match(urlRegex)) { - return ( - e.stopPropagation()} - > - {part} - - ); - } - return part; - })} -
- ); - })} - - ); -} export function FormLayoutClient({ userName, @@ -119,10 +89,6 @@ interface FormFillerClientProps { const LS_KEY = (formId: string) => `form-draft-${formId}`; const QUESTIONS_PER_STEP = 3; -const stripHtml = (html: string) => { - return (html || "").replace(/<[^>]*>?/gm, '').trim(); -}; - const buildSchema = (questions: Question[]) => { const shape: Record = {}; questions.forEach(q => { @@ -315,10 +281,7 @@ export function FormFillerClient({ form, questions, initialAnswers = {} }: FormF

-
+
{q.imageUrl && ( diff --git a/components/formatted-text.tsx b/components/formatted-text.tsx new file mode 100644 index 0000000..22a5fc7 --- /dev/null +++ b/components/formatted-text.tsx @@ -0,0 +1,36 @@ +import React from "react"; + +export function FormattedText({ text }: { text: string }) { + const lines = text.split('\n'); + const urlRegex = /(https?:\/\/[^\s]+)/g; + + return ( + <> + {lines.map((line, i) => { + const parts = line.split(urlRegex); + return ( + + {i > 0 &&
} + {parts.map((part, j) => { + if (part.match(urlRegex)) { + return ( + e.stopPropagation()} + > + {part} + + ); + } + return part; + })} +
+ ); + })} + + ); +} diff --git a/components/html-display.tsx b/components/html-display.tsx new file mode 100644 index 0000000..f6180db --- /dev/null +++ b/components/html-display.tsx @@ -0,0 +1,18 @@ +import * as React from "react" +import { cn } from "@/lib/utils" + +export interface HtmlDisplayProps extends React.HTMLAttributes { + html?: string | null; +} + +export function HtmlDisplay({ html, className, ...props }: HtmlDisplayProps) { + if (!html) return null; + + return ( +
p]:m-0", className)} + dangerouslySetInnerHTML={{ __html: html }} + {...props} + /> + ) +} diff --git a/components/ui/rich-text-editor.tsx b/components/rich-text-editor.tsx similarity index 100% rename from components/ui/rich-text-editor.tsx rename to components/rich-text-editor.tsx diff --git a/lib/utils.ts b/lib/utils.ts index bd0c391..d1cf4aa 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -4,3 +4,7 @@ import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } + +export const stripHtml = (html: string) => { + return (html || "").replace(/<[^>]*>?/gm, '').trim(); +};