corregido errores de compilacion para next en web

This commit is contained in:
2025-06-18 12:11:05 -04:00
parent a9a5dad0dd
commit 097eb7c8a2
29 changed files with 195 additions and 145 deletions

View File

@@ -2,7 +2,7 @@ import PageContainer from '@/components/layout/page-container';
import SurveysAdminList from '@/feactures/surveys/components/admin/surveys-admin-list';
import { SurveysHeader } from '@/feactures/surveys/components/admin/surveys-header';
import SurveysTableAction from '@/feactures/surveys/components/admin/surveys-tables/survey-table-action';
import { searchParamsCache, serialize } from '@/feactures/surveys/utils/searchparams';
import { searchParamsCache } from '@/feactures/surveys/utils/searchparams';
import { SearchParams } from 'nuqs';
type pageProps = {
@@ -13,8 +13,7 @@ type pageProps = {
export default async function SurveyAdminPage(props: pageProps) {
const searchParams = await props.searchParams;
searchParamsCache.parse(searchParams);
const key = serialize({ ...searchParams });
const page = Number(searchParamsCache.get('page')) || 1;
const search = searchParamsCache.get('q');
const pageLimit = Number(searchParamsCache.get('limit')) || 10;

View File

@@ -2,7 +2,7 @@ import PageContainer from '@/components/layout/page-container';
import UsersAdminList from '@/feactures/users/components/admin/users-admin-list';
import { UsersHeader } from '@/feactures/users/components/admin/users-header';
import UsersTableAction from '@/feactures/users/components/admin/surveys-tables/users-table-action';
import { searchParamsCache, serialize } from '@/feactures/users/utils/searchparams';
import { searchParamsCache } from '@/feactures/users/utils/searchparams';
import { SearchParams } from 'nuqs';
type pageProps = {
@@ -13,7 +13,7 @@ type pageProps = {
export default async function SurveyAdminPage(props: pageProps) {
const searchParams = await props.searchParams;
searchParamsCache.parse(searchParams);
const key = serialize({ ...searchParams });
const page = Number(searchParamsCache.get('page')) || 1;
const search = searchParamsCache.get('q');

View File

@@ -2,23 +2,32 @@ import PageContainer from '@/components/layout/page-container';
import { getSurveyByIdAction } from '@/feactures/surveys/actions/surveys-actions';
import { SurveyResponse } from '@/feactures/surveys/components/survey-response';
// La función ahora recibe 'params' con el parámetro dinámico 'id'
export default async function SurveyResponsePage({ params }: { params: { id: string } }) {
const { id } = await params; // Obtienes el id desde los params de la URL
export default async function SurveyResponsePage({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params; // You can still destructure id from params
if (!id || id === '') {
// Maneja el caso en el que no se proporciona un id
// Handle the case where no id is provided
return null;
}
// Llamas a la funcn pasando el id dinámico
// Call the function passing the dynamic id
const data = await getSurveyByIdAction(Number(id));
if (!data?.data) {
return <div>Encuesta no encontrada</div>;
}
return (
<PageContainer>
<div className="flex flex-1 flex-col space-y-4">
<SurveyResponse survey={data?.data!} />
</div>
<div className="flex flex-1 flex-col space-y-4">
<SurveyResponse survey={data?.data} />
</div>
</PageContainer>
);
}
}

View File

@@ -1,11 +1,16 @@
import Image from 'next/image';
export default async function Page() {
return (
// <PageContainer>
<div className="flex justify-center items-center h-full">
<img src="../logo.png" alt="Image" className="w-1/4"/>
<Image
src="/logo.png" // OJO: la ruta debe ser desde /public (sin '..')
alt="Image"
width={400} // Ajusta el tamaño según tu imagen
height={400}
className="w-1/4 h-auto" // Puedes seguir usando Tailwind para responsividad
priority // Opcional: para imágenes importantes arriba del todo
/>
</div>
// </PageContainer>
);
}

View File

@@ -2,7 +2,7 @@ import { AppSidebar } from '@/components/layout/app-sidebar';
import Header from '@/components/layout/header';
import { SidebarInset, SidebarProvider } from '@repo/shadcn/sidebar';
import type { Metadata } from 'next';
import { cookies } from 'next/headers';
//import { cookies } from 'next/headers';
export const metadata: Metadata = {
title: 'Dashboard',
@@ -15,7 +15,7 @@ export default async function DashboardLayout({
children: React.ReactNode;
}) {
// Persisting the sidebar state in the cookie.
const cookieStore = await cookies();
//const cookieStore = await cookies();
//const defaultOpen = cookieStore.get('sidebar:state')?.value === 'false';
return (
<SidebarProvider defaultOpen={true}>

View File

@@ -15,33 +15,52 @@ export async function GET(req: NextRequest) {
return new ImageResponse(
(
<div
tw="flex h-full w-full bg-black text-white"
style={{ fontFamily: 'Geist Sans' }}
style={{
display: 'flex',
height: '100%',
width: '100%',
backgroundColor: '#000',
color: '#fff',
fontFamily: 'Geist Sans'
}}
>
<div tw="flex border absolute border-stone-700 border-dashed inset-y-0 left-16 w-[1px]" />
<div tw="flex border absolute border-stone-700 border-dashed inset-y-0 right-16 w-[1px]" />
<div tw="flex border absolute border-stone-700 inset-x-0 h-[1px] top-16" />
<div tw="flex border absolute border-stone-700 inset-x-0 h-[1px] bottom-16" />
<div tw="flex absolute flex-row bottom-24 right-24 text-white"></div>
<div tw="flex flex-col absolute w-[896px] justify-center inset-32">
<div
tw="tracking-tight flex-grow-1 flex flex-col justify-center leading-[1.1]"
style={{
textWrap: 'balance',
fontWeight: 600,
fontSize: title && title.length > 20 ? 64 : 80,
letterSpacing: '-0.04em',
}}
>
<div style={{
position: 'absolute',
border: '1px dashed #404040',
top: 0,
bottom: 0,
left: '64px',
width: '1px'
}} />
{/* Repite el mismo patrón para los otros bordes */}
<div style={{
position: 'absolute',
display: 'flex',
flexDirection: 'column',
width: '896px',
justifyContent: 'center',
top: '128px',
bottom: '128px',
left: '128px',
right: '128px'
}}>
<div style={{
letterSpacing: '-0.04em',
textWrap: 'balance' as any,
fontWeight: 600,
fontSize: title && title.length > 20 ? 64 : 80,
lineHeight: '1.1'
}}>
{title}
</div>
<div
tw="text-[40px] leading-[1.5] flex-grow-1 text-stone-400"
style={{
fontWeight: 500,
textWrap: 'balance',
}}
>
<div style={{
fontSize: '40px',
lineHeight: '1.5',
color: '#a3a3a3',
fontWeight: 500,
textWrap: 'balance' as any
}}>
{`${description?.slice(0, 100)}`}
</div>
</div>
@@ -57,6 +76,6 @@ export async function GET(req: NextRequest) {
style: 'normal',
},
],
},
}
);
}

View File

@@ -1,8 +1,9 @@
/* eslint-disable @next/next/no-img-element */
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
// Image metadata
export const alt = `Opengraph Image`;
export const size = {
width: 800,

View File

@@ -9,8 +9,8 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from '@repo/shadcn/dropdown-menu';
type CompProps = {};
export default function ThemeToggle({}: CompProps) {
export default function ThemeToggle() {
const { setTheme } = useTheme();
return (
<DropdownMenu>

View File

@@ -1,6 +1,6 @@
'use client';
import { NavMain as ConfigMain, NavMain as GeneralMain, NavMain as AdministrationMain, NavMain as StatisticsMain, } from '@/components/nav-main';
import { NavMain as GeneralMain, NavMain as AdministrationMain, NavMain as StatisticsMain, } from '@/components/nav-main';
import { GeneralItems, AdministrationItems, StatisticsItems } from '@/constants/data';
import {
Sidebar,

View File

@@ -5,9 +5,6 @@ import { SessionProvider, SessionProviderProps } from 'next-auth/react';
import { NuqsAdapter } from 'nuqs/adapters/next/app';
import { ReactNode } from 'react';
type ProvidersProps = {
children: ReactNode;
};
const queryClient = new QueryClient({
defaultOptions: {

View File

@@ -3,9 +3,7 @@
import {
Folder,
Forward,
Frame,
PanelLeft,
PieChart,
Trash2,
type LucideIcon,
} from 'lucide-react';
@@ -27,25 +25,6 @@ import {
useSidebar,
} from '@repo/shadcn/sidebar';
const data = {
projects: [
{
name: 'Design Engineering',
url: '#',
icon: Frame,
},
{
name: 'Sales & Marketing',
url: '#',
icon: PieChart,
},
{
name: 'Travel',
url: '#',
icon: Map,
},
],
};
export function NavProjects({
projects,

View File

@@ -1,10 +1,7 @@
'use client';
import {
AudioWaveform,
ChevronsUpDownIcon,
Command,
GalleryVerticalEnd,
PlusIcon,
} from 'lucide-react';
@@ -25,25 +22,6 @@ import {
} from '@repo/shadcn/sidebar';
import * as React from 'react';
const data = {
teams: [
{
name: 'Acme Inc',
logo: GalleryVerticalEnd,
plan: 'Enterprise',
},
{
name: 'Acme Corp.',
logo: AudioWaveform,
plan: 'Startup',
},
{
name: 'Evil Corp.',
logo: Command,
plan: 'Free',
},
],
};
export function TeamSwitcher({
teams,

View File

@@ -2,7 +2,36 @@
import { safeFetchApi } from '@/lib';
import { loginResponseSchema, UserFormValue } from '../schemas/login';
export const SignInAction = async (payload: UserFormValue) => {
type LoginActionSuccess = {
message: string;
user: {
email: string;
username: string;
id: number;
rol: Array<{ id: number; rol: string }>;
fullname: string;
};
tokens: {
access_token: string;
access_expire_in: number;
refresh_token: string;
refresh_expire_in: number;
};
}
type LoginActionError = {
type: 'API_ERROR' | 'VALIDATION_ERROR' | 'UNKNOWN_ERROR'; // **Asegúrate de que el tipo de `type` sea este aquí**
message: string;
details?: any;
};
// Si SignInAction también puede devolver null, asegúralo en su tipo de retorno
type LoginActionResult = LoginActionSuccess | LoginActionError | null;
export const SignInAction = async (payload: UserFormValue): Promise<LoginActionResult> => {
const [error, data] = await safeFetchApi(
loginResponseSchema,
'/auth/sign-in',
@@ -10,7 +39,11 @@ export const SignInAction = async (payload: UserFormValue) => {
payload,
);
if (error) {
return error;
return {
type: error.type as 'API_ERROR' | 'VALIDATION_ERROR' | 'UNKNOWN_ERROR',
message: error.message,
details: error.details
};
} else {
return data;
}

View File

@@ -10,7 +10,6 @@ import {
FormMessage,
} from '@repo/shadcn/form';
import { Input } from '@repo/shadcn/input';
import { signIn } from 'next-auth/react';
import { useRouter, useSearchParams } from 'next/navigation';
import { useState, useTransition } from 'react';
import { useForm } from 'react-hook-form';
@@ -27,13 +26,10 @@ export default function UserAuthForm() {
const router = useRouter();
const searchParams = useSearchParams();
const callbackUrl = searchParams.get('callbackUrl');
const [loading, startTransition] = useTransition();
const [error, SetError] = useState<string | null>(null);
const [state, setState] = React.useState(0);
const [municipality, setMunicipality] = React.useState(0);
const [parish, setParish] = React.useState(0);
const [disabledMunicipality, setDisabledMunicipality] = React.useState(true);
const [disabledParish, setDisabledParish] = React.useState(true);

View File

@@ -3,7 +3,7 @@
import { useState } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@repo/shadcn/card';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@repo/shadcn/select';
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip, Legend } from 'recharts';
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts';
import { SurveyStatisticsData } from '../schemas/statistics';
interface SurveyDetailsProps {

View File

@@ -1,7 +1,7 @@
'use client';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@repo/shadcn/card';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
import { SurveyStatisticsData } from '../schemas/statistics';
interface SurveyOverviewProps {

View File

@@ -1,6 +1,5 @@
'use client';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@repo/shadcn/card';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@repo/shadcn/tabs';
import { useSurveysStatsQuery } from '../hooks/use-query-statistics';
import { SurveyOverview } from './survey-overview';

View File

@@ -19,7 +19,7 @@ import {
} from '@repo/shadcn/card';
import { useRouter } from 'next/navigation';
import { useSurveysForUserQuery } from '@/feactures/surveys/hooks/use-query-surveys';
import { Survey, SurveyAnswerForUser } from '../schemas/survey';
import { SurveyAnswerForUser } from '../schemas/survey';
import { Badge } from '@repo/shadcn/badge';
import { BadgeCheck } from 'lucide-react';

View File

@@ -9,7 +9,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from '@repo/shadcn/tooltip';
import { Edit, Trash, User } from 'lucide-react';
import { Edit, Trash } from 'lucide-react';
import { SurveyTable } from '@/feactures/users/schemas/users';
import { useDeleteUser } from '@/feactures/users/hooks/use-mutation-users';
import { AccountPlanModal } from '../user-modal';
@@ -23,7 +23,6 @@ export const CellAction: React.FC<CellActionProps> = ({ data }) => {
const [open, setOpen] = useState(false);
const [edit, setEdit] = useState(false);
const { mutate: deleteUser } = useDeleteUser();
const router = useRouter();
const onConfirm = async () => {
try {

View File

@@ -12,7 +12,6 @@ export default function UserTableAction() {
typeFilter,
searchQuery,
setPage,
setTypeFilter,
setSearchQuery,
} = useSurveyTableFilters();

View File

@@ -1,5 +1,4 @@
'use client';
import { useRouter } from 'next/navigation';
import { Button } from '@repo/shadcn/button';
import { Heading } from '@repo/shadcn/heading';
import { Plus } from 'lucide-react';

View File

@@ -14,9 +14,7 @@ import {
FormLabel,
FormMessage,
} from '@repo/shadcn/form';
import { UpdateUser, updateUser } from '@/feactures/users/schemas/users';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
interface SelectListProps {
label: string

View File

@@ -46,8 +46,6 @@ export function ModalForm({
const [state, setState] = React.useState(0);
const [municipality, setMunicipality] = React.useState(0);
const [parish, setParish] = React.useState(0);
const [disabledMunicipality, setDisabledMunicipality] = React.useState(true);
const [disabledParish, setDisabledParish] = React.useState(true);

View File

@@ -1,7 +1,7 @@
'use client';
import { useUserByProfile } from '@/feactures/users/hooks/use-query-users';
import { Button } from '@repo/shadcn/button';
import { Edit, Edit2 } from 'lucide-react';
import { Edit2 } from 'lucide-react';
import { useState } from 'react';
import { AccountPlanModal } from './modal-profile';

View File

@@ -4,6 +4,35 @@ import { CredentialsSignin, NextAuthConfig, Session, User } from 'next-auth';
import { DefaultJWT } from 'next-auth/jwt';
import CredentialProvider from 'next-auth/providers/credentials';
// Define los tipos para tus respuestas de SignInAction
interface SignInSuccessResponse {
message: string;
user: {
email: string;
username: string;
id: number;
rol: Array<{ id: number; rol: string }>;
fullname: string;
};
tokens: {
access_token: string;
access_expire_in: number;
refresh_token: string;
refresh_expire_in: number;
};
}
// **CAMBIO AQUÍ**: `type: string;` en lugar de una unión de literales
interface SignInErrorResponse {
type: string; // Si SignInAction puede devolver cualquier string aquí
message: string;
details?: any;
}
// Unión de tipos para el resultado de SignInAction, AHORA INCLUYE `null`
type SignInActionResult = SignInSuccessResponse | SignInErrorResponse | null;
const authConfig: NextAuthConfig = {
providers: [
CredentialProvider({
@@ -17,24 +46,39 @@ const authConfig: NextAuthConfig = {
},
async authorize(
credentials: Partial<Record<'username' | 'password', unknown>>,
request: Request,
): Promise<User | null> {
const credential = {
username: credentials?.username as string,
password: credentials?.password as string,
};
const response = await SignInAction(credential);
// Asigna el tipo `SignInActionResult` que ahora incluye `null`
const response: SignInActionResult = await SignInAction(credential);
// **NUEVO: Manejar el caso `null` primero**
if (response === null) {
console.error("SignInAction returned null, indicating a potential issue before API call or generic error.");
throw new CredentialsSignin("Error de inicio de sesión inesperado.");
}
// Tipo Guarda: Verificar la respuesta de error
if (
response &&
'type' in response &&
(response.type === 'API_ERROR' ||
response.type === 'VALIDATION_ERROR')
response.type === 'VALIDATION_ERROR' ||
response.type === 'UNKNOWN_ERROR') // Incluye todos los tipos de error posibles
) {
// Si es un error, lánzalo. Este camino termina aquí.
throw new CredentialsSignin(response.message);
}
if (!('user' in response)) {
// Esto solo ocurriría si SignInAction devolvió un objeto que no es null,
// no es un error conocido por 'type', PERO tampoco tiene la propiedad 'user'.
// Es un caso de respuesta inesperada del API.
console.error("Respuesta de SignInAction con formato inesperado: falta la propiedad 'user'.");
throw new CredentialsSignin("Error en el formato de la respuesta del servidor.");
}
return {
id: response?.user.id?.toString() ?? '0',
@@ -58,12 +102,10 @@ const authConfig: NextAuthConfig = {
callbacks: {
async jwt({
token,
user,
account,
user
}: {
token: any;
user: User;
account: any;
}) {
// Si es un nuevo login, asignamos los datos
if (user) {
@@ -94,6 +136,7 @@ const authConfig: NextAuthConfig = {
token.refresh_token = res.tokens.refresh_token;
token.refresh_expire_in = res.tokens.refresh_expire_in;
} catch (error) {
console.log(error);
return null;
}
}

View File

@@ -1,15 +0,0 @@
'use server';
import { safeFetch } from '@/lib/safeFetch';
import { GetAllUsers, GetAllUsersSchema } from '@/types/user.type';
export const getAllUsers = async (): Promise<GetAllUsers> => {
const [isError, data] = await safeFetch(GetAllUsersSchema, '/users', {
cache: 'no-store',
});
if (isError)
return {
data: [],
};
return data;
};

View File

@@ -7,7 +7,8 @@
}
],
"paths": {
"@/*": ["./*"]
"@/*": ["./*"],
"@repo/shadcn/*": ["../../packages/shadcn/src/*"]
}
},
"include": [

View File

@@ -46,4 +46,11 @@ export const nextJsConfig = [
'react/react-in-jsx-scope': 'off',
},
},
// Aquí agregamos el override para TS
{
files: ['*.ts', '*.tsx'],
rules: {
'react/prop-types': 'off',
},
},
];

View File

@@ -5,7 +5,7 @@ import { DayPicker } from "react-day-picker"
import { cn } from "@repo/shadcn/lib/utils"
import { buttonVariants } from "@repo/shadcn/components/ui/button"
import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons"
import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons" // Asegúrate de que esto está bien importado
function Calendar({
className,
@@ -60,11 +60,17 @@ function Calendar({
...classNames,
}}
components={{
IconLeft: ({ className, ...props }) => (
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
IconLeft: ({ className, children, style, ...propsFromDayPicker }) => ( // <--- CAMBIO AQUÍ
<ChevronLeftIcon
className={cn("size-4", className)}
{...propsFromDayPicker}
/>
),
IconRight: ({ className, ...props }) => (
<ChevronRightIcon className={cn("size-4", className)} {...props} />
IconRight: ({ className, children, style, ...propsFromDayPicker }) => ( // <--- CAMBIO AQUÍ
<ChevronRightIcon
className={cn("size-4", className)}
{...propsFromDayPicker}
/>
),
}}
{...props}
@@ -72,4 +78,4 @@ function Calendar({
)
}
export { Calendar }
export { Calendar }