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,13 @@
'use client';
import {
ThemeProvider as NextThemesProvider,
ThemeProviderProps
} from 'next-themes';
export default function ThemeProvider({
children,
...props
}: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}

View File

@@ -0,0 +1,37 @@
'use client';
import { MoonIcon, SunIcon } from 'lucide-react';
import { useTheme } from 'next-themes';
import { Button } from '@repo/shadcn/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@repo/shadcn/dropdown-menu';
type CompProps = {};
export default function ThemeToggle({}: CompProps) {
const { setTheme } = useTheme();
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
<SunIcon className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<MoonIcon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme('light')}>
Light
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme('dark')}>
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme('system')}>
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

View File

@@ -0,0 +1,58 @@
'use client';
import { NavMain as ConfigMain, NavMain as GeneralMain, NavMain as AdministrationMain, NavMain as StatisticsMain, } from '@/components/nav-main';
import { GeneralItems, AdministrationItems, StatisticsItems } from '@/constants/data';
import {
Sidebar,
SidebarContent,
SidebarHeader,
SidebarRail,
} from '@repo/shadcn/sidebar';
import { GalleryVerticalEnd } from 'lucide-react';
import * as React from 'react';
// import { NavItem } from '@/types';
import { useSession } from 'next-auth/react';
export const company = {
name: 'Sistema',
logo: GalleryVerticalEnd,
plan: 'FONDEMI',
};
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
const { data: session } = useSession();
const userRole = session?.user.role[0]?.rol ? session.user.role[0].rol :'';
// console.log(AdministrationItems[0]?.role);
return (
<Sidebar collapsible="icon" {...props}>
<SidebarHeader>
<div className="flex gap-2 py-2 text-sidebar-accent-foreground">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<company.logo className="size-4" />
</div>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">{company.name}</span>
<span className="truncate text-xs">{company.plan}</span>
</div>
</div>
</SidebarHeader>
<SidebarContent>
<GeneralMain titleGroup={'General'} items={GeneralItems} role={userRole}/>
{StatisticsItems[0]?.role?.includes(userRole) &&
<StatisticsMain titleGroup={'Estadisticas'} items={StatisticsItems} role={userRole}/>
}
{AdministrationItems[0]?.role?.includes(userRole) &&
<AdministrationMain titleGroup={'Administracion'} items={AdministrationItems} role={userRole}/>
}
{/* <NavProjects projects={data.projects} /> */}
</SidebarContent>
<SidebarRail />
</Sidebar>
);
}

View File

@@ -0,0 +1,25 @@
import { Separator } from '@repo/shadcn/separator';
import { SidebarTrigger } from '@repo/shadcn/sidebar';
import { Breadcrumbs } from '../breadcrumbs';
import ThemeToggle from './ThemeToggle/theme-toggle';
import { UserNav } from './user-nav';
export default function Header() {
return (
<header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
<Separator
orientation="vertical"
className="mr-2 data-[orientation=vertical]:h-4"
/>
<Breadcrumbs />
</div>
<div className="flex items-center gap-2 px-4 ml-auto">
<ThemeToggle />
<UserNav />
</div>
</header>
);
}

View File

@@ -0,0 +1,22 @@
import { ScrollArea } from '@repo/shadcn/scroll-area';
import React from 'react';
export default function PageContainer({
children,
scrollable = true,
}: {
children: React.ReactNode;
scrollable?: boolean;
}) {
return (
<>
{scrollable ? (
<ScrollArea className="h-[calc(100dvh-52px)]">
<div className="flex flex-1 p-4 md:px-6">{children}</div>
</ScrollArea>
) : (
<div className="flex flex-1 p-4 md:px-6">{children}</div>
)}
</>
);
}

View File

@@ -0,0 +1,48 @@
'use client';
import { ThemeProvider } from '@repo/shadcn/themes-provider';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
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: {
queries: {
retry: 2,
gcTime: 60 * 60 * 1000, // 1 hora para garbage collection
staleTime: 60 * 60 * 1000, // 1 hora para considerar datos obsoletos
refetchOnWindowFocus: false, // No recargar al enfocar la ventana
refetchOnMount: true, // Recargar al montar el componente
},
},
});
const Providers = ({
session,
children,
}: {
session: SessionProviderProps['session'];
children: ReactNode;
}) => {
return (
<>
<QueryClientProvider client={queryClient}>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange={false}
>
<NuqsAdapter>
<SessionProvider session={session}>{children}</SessionProvider>
</NuqsAdapter>
</ThemeProvider>
</QueryClientProvider>
</>
);
};
export default Providers;

View File

@@ -0,0 +1,52 @@
'use client';
import { Avatar, AvatarFallback, AvatarImage } from '@repo/shadcn/avatar';
import { Button } from '@repo/shadcn/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@repo/shadcn/dropdown-menu';
import { signOut, useSession } from 'next-auth/react';
import { redirect } from 'next/navigation';
export function UserNav() {
const { data: session } = useSession();
if (session) {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="relative h-9 w-9 rounded-full">
<Avatar className="h-9 w-9">
<AvatarImage src={''} alt={session.user?.fullname ?? ''} />
<AvatarFallback>{session.user?.fullname?.[0]}</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56" align="end" forceMount>
<DropdownMenuLabel className="font-normal">
<div className="flex flex-col space-y-1">
<p className="text-sm font-medium leading-none">
{session.user?.fullname}
</p>
<p className="text-xs leading-none text-muted-foreground">
{session.user?.email}
</p>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem onClick={()=> redirect('/dashboard/profile')}>Perfil</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => signOut()}>
Cerrar Sessión
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
}