style: IDK WHAT IUS FUCKING ON
This commit is contained in:
@@ -201,7 +201,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
});
|
||||
router.refresh();
|
||||
} catch (err: unknown) {
|
||||
toast.error(getErrorMessage(err, "Could not delete the question."));
|
||||
toast.error(getErrorMessage(err, "Could not remove the question."));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -407,19 +407,53 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
<AccordionItem value={q.id} className="border-0">
|
||||
<Card>
|
||||
<CardHeader className="pl-12">
|
||||
<AccordionTrigger className="py-0 hover:no-underline">
|
||||
<div className="min-w-0 text-left">
|
||||
<CardTitle className="truncate text-base">
|
||||
{stripHtml(q.label) || `Untitled question ${index + 1}`}
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Question {index + 1} · {questionTypeLabel(q.type)}
|
||||
{q.required ? " · Required" : ""}
|
||||
</CardDescription>
|
||||
<div className="relative flex items-center">
|
||||
<div className="min-w-0 flex-1">
|
||||
<AccordionTrigger className="w-full min-w-0 py-0 pr-32 hover:no-underline [&_[data-slot=accordion-trigger-icon]]:absolute [&_[data-slot=accordion-trigger-icon]]:right-0 [&_[data-slot=accordion-trigger-icon]]:top-1/2 [&_[data-slot=accordion-trigger-icon]]:-translate-y-1/2">
|
||||
<div className="min-w-0 text-left">
|
||||
<CardTitle className="truncate text-base">
|
||||
{stripHtml(q.label) || `Untitled question ${index + 1}`}
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Question {index + 1} · {questionTypeLabel(q.type)}
|
||||
{q.required ? " · Required" : ""}
|
||||
</CardDescription>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="absolute right-8 top-1/2 -translate-y-1/2 text-destructive"
|
||||
aria-label={`Remove question ${index + 1}`}
|
||||
>
|
||||
<Trash data-icon="inline-start" />
|
||||
Remove
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Remove question {index + 1}?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This permanently removes the question and its stored answers.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Keep question</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
variant="destructive"
|
||||
onClick={() => void handleDeleteQuestion(q.id)}
|
||||
>
|
||||
Remove question
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<AccordionContent>
|
||||
<AccordionContent className="h-auto">
|
||||
<CardContent className="flex flex-col gap-4 pt-0">
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-4">
|
||||
<div className="flex-1 w-full">
|
||||
@@ -431,23 +465,6 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 self-end sm:self-auto">
|
||||
<Select
|
||||
value={q.type}
|
||||
onValueChange={(val) => handleUpdateQuestion(q.id, { type: val as Question["type"] })}
|
||||
>
|
||||
<SelectTrigger className="w-36">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="text">Short answer</SelectItem>
|
||||
<SelectItem value="textarea">Paragraph</SelectItem>
|
||||
<SelectItem value="radio">Choose one</SelectItem>
|
||||
<SelectItem value="checkbox">Choose multiple</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<div className="flex items-center gap-1 border rounded-md p-1">
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -470,6 +487,23 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
<ArrowDown />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Select
|
||||
value={q.type}
|
||||
onValueChange={(val) => handleUpdateQuestion(q.id, { type: val as Question["type"] })}
|
||||
>
|
||||
<SelectTrigger className="w-36">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="text">Short answer</SelectItem>
|
||||
<SelectItem value="textarea">Paragraph</SelectItem>
|
||||
<SelectItem value="radio">Choose one</SelectItem>
|
||||
<SelectItem value="checkbox">Choose multiple</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -570,51 +604,18 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex justify-between items-center pt-2 border-t border-border">
|
||||
<div className="flex items-center flex-wrap gap-6">
|
||||
{(q.type === "radio" || q.type === "checkbox") && (
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch
|
||||
id={`allowOther-${q.id}`}
|
||||
checked={q.allowOther}
|
||||
onCheckedChange={(checked) => handleUpdateQuestion(q.id, { allowOther: checked })}
|
||||
/>
|
||||
<Label htmlFor={`allowOther-${q.id}`} className="text-sm font-normal text-muted-foreground">
|
||||
Add 'Other' option
|
||||
</Label>
|
||||
</div>
|
||||
)}
|
||||
{(q.type === "radio" || q.type === "checkbox") && (
|
||||
<div className="flex items-center gap-2 border-t border-border pt-2">
|
||||
<Switch
|
||||
id={`allowOther-${q.id}`}
|
||||
checked={q.allowOther}
|
||||
onCheckedChange={(checked) => handleUpdateQuestion(q.id, { allowOther: checked })}
|
||||
/>
|
||||
<Label htmlFor={`allowOther-${q.id}`} className="text-sm font-normal text-muted-foreground">
|
||||
Add 'Other' option
|
||||
</Label>
|
||||
</div>
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="text-destructive hover:bg-destructive/10"
|
||||
aria-label={`Delete question ${index + 1}`}
|
||||
>
|
||||
<Trash />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Delete question {index + 1}?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This permanently removes the question and its stored answers.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Keep question</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
variant="destructive"
|
||||
onClick={() => void handleDeleteQuestion(q.id)}
|
||||
>
|
||||
Delete question
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</AccordionContent>
|
||||
</Card>
|
||||
|
||||
@@ -106,9 +106,12 @@ export default async function ResultsListPage({
|
||||
Array.isArray(submission.editHistory) &&
|
||||
submission.editHistory.length > 0;
|
||||
return (
|
||||
<TableRow key={submission.id}>
|
||||
<TableRow key={submission.id} className="relative cursor-pointer">
|
||||
<TableCell>
|
||||
<Link href={detailHref} className="font-medium hover:underline">
|
||||
<Link
|
||||
href={detailHref}
|
||||
className="font-medium after:absolute after:inset-0 focus-visible:outline-none focus-visible:after:ring-2 focus-visible:after:ring-ring focus-visible:after:ring-inset"
|
||||
>
|
||||
{submission.userName ||
|
||||
submission.userDiscordId ||
|
||||
"Anonymous"}
|
||||
@@ -125,7 +128,7 @@ export default async function ResultsListPage({
|
||||
{edited ? "Edited" : "Original"}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<TableCell className="relative z-10 text-right">
|
||||
<DeleteSubmissionButton id={submission.id} compact />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -140,10 +143,16 @@ export default async function ResultsListPage({
|
||||
{rows.map((submission) => {
|
||||
const detailHref = `/admin/form/${id}/result/${submission.id}${listQuery ? `?return=${encodeURIComponent(listQuery)}` : ""}`;
|
||||
return (
|
||||
<Card key={submission.id}>
|
||||
<Card
|
||||
key={submission.id}
|
||||
className="relative transition-colors hover:bg-muted/50"
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">
|
||||
<Link href={detailHref}>
|
||||
<Link
|
||||
href={detailHref}
|
||||
className="after:absolute after:inset-0 focus-visible:outline-none focus-visible:after:ring-2 focus-visible:after:ring-ring focus-visible:after:ring-inset"
|
||||
>
|
||||
{submission.userName ||
|
||||
submission.userDiscordId ||
|
||||
"Anonymous"}
|
||||
@@ -154,7 +163,9 @@ export default async function ResultsListPage({
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex justify-end">
|
||||
<DeleteSubmissionButton id={submission.id} compact />
|
||||
<div className="relative z-10">
|
||||
<DeleteSubmissionButton id={submission.id} compact />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@@ -2,9 +2,6 @@ import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
serverExternalPackages: ["bun"],
|
||||
experimental: {
|
||||
turbopackFileSystemCacheForBuild: true,
|
||||
},
|
||||
turbopack: {
|
||||
root: process.cwd(),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user