base con autenticacion, registro, modulo encuestas

This commit is contained in:
2025-06-16 12:02:22 -04:00
commit 475e0754df
411 changed files with 26265 additions and 0 deletions

View File

@@ -0,0 +1,252 @@
'use client';
import { Button } from '@repo/shadcn/button';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@repo/shadcn/card';
import { Checkbox } from '@repo/shadcn/checkbox';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@repo/shadcn/form';
import { Input } from '@repo/shadcn/input';
import { RadioGroup, RadioGroupItem } from '@repo/shadcn/radio-group';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@repo/shadcn/select';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import { Question, type SurveyResponse, SurveyTable } from '../schemas/survey';
import { useSurveyAnswerMutation } from '../hooks/use-mutation-surveys';
interface SurveyResponseProps {
survey: SurveyTable;
}
export function SurveyResponse({ survey }: SurveyResponseProps) {
const router = useRouter();
const [loading, setLoading] = useState(false);
const form = useForm({
defaultValues: {
// Initialize an empty object for each question
...Object.fromEntries(
survey.questions.map((question) => [question.id, ''])
)
}
});
const {
mutate: MutateAnswer,
} = useSurveyAnswerMutation()
const handleSubmit = async (data: any) => {
setLoading(true);
const answers = Object.entries(data).map(([questionId, value]) => ({
questionId,
value,
}));
const response: SurveyResponse = {
surveyId: String(survey.id),
answers: answers.map(answer => ({
questionId: answer.questionId,
value: String(answer.value)
})),
};
try {
await MutateAnswer({
...response
}, {
onSuccess: () => {
toast.success('Encuesta enviada exitosamente');
router.push('/dashboard/encuestas');
},
onError: () => {
toast.error('Error al enviar la encuesta');
}
}
)
} catch (error) {
toast.error('Error al enviar la encuesta');
}
};
const renderQuestion = (question: Question) => {
switch (question.type) {
case 'title':
return (
<div className="py-4">
<h3 className="text-lg font-semibold">{question.content}</h3>
</div>
);
case 'simple':
return (
<FormField
control={form.control}
name={question.id}
render={({ field }) => (
<FormItem>
<FormLabel className='pb-2'>{question.question}</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
);
case 'multiple_choice':
return (
<FormField
control={form.control}
name={question.id}
render={() => (
<FormItem>
<FormLabel className='pb-2'>{question.question}</FormLabel>
<div className="space-y-2">
{question.options.map((option) => (
<FormField
key={option.id}
control={form.control}
name={`${question.id}.${option.id}`}
render={({ field }) => (
<FormItem className="flex items-center space-x-3">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<FormLabel className="font-normal">
{option.text}
</FormLabel>
</FormItem>
)}
/>
))}
</div>
<FormMessage />
</FormItem>
)}
/>
);
case 'single_choice':
return (
<FormField
control={form.control}
name={question.id}
render={({ field }) => (
<FormItem>
<FormLabel className='pb-2'>{question.question}</FormLabel>
<FormControl>
<RadioGroup
onValueChange={field.onChange}
defaultValue={field.value}
className="space-y-2"
>
{question.options.map((option) => (
<FormItem
key={option.id}
className="flex items-center space-x-3"
>
<FormControl>
<RadioGroupItem value={option.id} />
</FormControl>
<FormLabel className="font-normal">
{option.text}
</FormLabel>
</FormItem>
))}
</RadioGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
);
case 'select':
return (
<FormField
control={form.control}
name={question.id}
render={({ field }) => (
<FormItem>
<FormLabel className='pb-2'>{question.question}</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Seleccione una opción" />
</SelectTrigger>
</FormControl>
<SelectContent>
{question.options.map((option) => (
<SelectItem key={option.id} value={option.id}>
{option.text}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
);
}
};
return (
<div className=" w-full">
<Card className="w-full">
<CardHeader>
<CardTitle>{survey.title}</CardTitle>
<CardDescription>{survey.description}</CardDescription>
</CardHeader>
<CardContent className="p-6">
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
{survey.questions.map((question) => (
<div key={question.id}>{renderQuestion(question)}</div>
))}
<div className="flex gap-4 justify-end">
<Button
type="button"
variant="outline"
onClick={() => router.back()}
disabled={loading}
>
Cancelar
</Button>
<Button type="submit" disabled={loading}>
Enviar
</Button>
</div>
</form>
</Form>
</CardContent>
</Card>
</div>
);
}