This commit is contained in:
David Arranz 2024-08-29 16:59:33 +02:00
parent e6cd348c13
commit b1cf2fdd18
8 changed files with 29 additions and 446 deletions

View File

@ -21,5 +21,5 @@ export const StartPage = () => {
); );
} }
return <Navigate to={"/home"} replace />; return <Navigate to={"/quotes"} replace />;
}; };

View File

@ -1,49 +1,6 @@
import {
ChevronLeft,
ChevronRight,
Copy,
CreditCard,
File,
ListFilter,
MoreVertical,
Truck,
} from "lucide-react";
import { Layout, LayoutContent, LayoutHeader } from "@/components"; import { Layout, LayoutContent, LayoutHeader } from "@/components";
import { useGetProfile } from "@/lib/hooks"; import { useGetProfile } from "@/lib/hooks";
import { import { Skeleton } from "@/ui";
Badge,
Button,
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
Pagination,
PaginationContent,
PaginationItem,
Progress,
Separator,
Skeleton,
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/ui";
import { t } from "i18next"; import { t } from "i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
@ -64,383 +21,6 @@ export const DashboardPage = () => {
) : ( ) : (
<Skeleton className='w-[100px] h-[20px] rounded-full' /> <Skeleton className='w-[100px] h-[20px] rounded-full' />
)} )}
<div className='grid items-start flex-1 gap-4 p-4 sm:px-6 sm:py-0 md:gap-8 lg:grid-cols-3 xl:grid-cols-3'>
<div className='grid items-start gap-4 auto-rows-max md:gap-8 lg:col-span-2'>
<div className='grid gap-4 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-2 xl:grid-cols-4'>
<Card className='sm:col-span-2' x-chunk='dashboard-05-chunk-0'>
<CardHeader className='pb-3'>
<CardTitle>Tus Cotizaciones</CardTitle>
<CardDescription className='max-w-lg leading-relaxed text-balance'>
Introducing Our Dynamic Orders Dashboard for Seamless Management and Insightful
Analysis.
</CardDescription>
</CardHeader>
<CardFooter>
<Button onClick={() => navigate("/quotes/add")}>
{t("quotes.create.title")}
</Button>
</CardFooter>
</Card>
<Card x-chunk='dashboard-05-chunk-1'>
<CardHeader className='pb-2'>
<CardDescription>This Week</CardDescription>
<CardTitle className='text-4xl'>$1,329</CardTitle>
</CardHeader>
<CardContent>
<div className='text-xs text-muted-foreground'>+25% from last week</div>
</CardContent>
<CardFooter>
<Progress value={25} aria-label='25% increase' />
</CardFooter>
</Card>
<Card x-chunk='dashboard-05-chunk-2'>
<CardHeader className='pb-2'>
<CardDescription>This Month</CardDescription>
<CardTitle className='text-4xl'>$5,329</CardTitle>
</CardHeader>
<CardContent>
<div className='text-xs text-muted-foreground'>+10% from last month</div>
</CardContent>
<CardFooter>
<Progress value={12} aria-label='12% increase' />
</CardFooter>
</Card>
</div>
<Tabs defaultValue='week'>
<div className='flex items-center'>
<TabsList>
<TabsTrigger value='week'>Week</TabsTrigger>
<TabsTrigger value='month'>Month</TabsTrigger>
<TabsTrigger value='year'>Year</TabsTrigger>
</TabsList>
<div className='flex items-center gap-2 ml-auto'>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant='outline' size='sm' className='gap-1 text-sm h-7'>
<ListFilter className='h-3.5 w-3.5' />
<span className='sr-only sm:not-sr-only'>Filter</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align='end'>
<DropdownMenuLabel>Filter by</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem checked>Fulfilled</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem>Declined</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem>Refunded</DropdownMenuCheckboxItem>
</DropdownMenuContent>
</DropdownMenu>
<Button size='sm' variant='outline' className='gap-1 text-sm h-7'>
<File className='h-3.5 w-3.5' />
<span className='sr-only sm:not-sr-only'>Export</span>
</Button>
</div>
</div>
<TabsContent value='week'>
<Card x-chunk='dashboard-05-chunk-3'>
<CardHeader className='px-7'>
<CardTitle>Orders</CardTitle>
<CardDescription>Recent orders from your store.</CardDescription>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead>Customer</TableHead>
<TableHead className='hidden sm:table-cell'>Type</TableHead>
<TableHead className='hidden sm:table-cell'>Status</TableHead>
<TableHead className='hidden md:table-cell'>Date</TableHead>
<TableHead className='text-right'>Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow className='bg-accent'>
<TableCell>
<div className='font-medium'>Liam Johnson</div>
<div className='hidden text-sm text-muted-foreground md:inline'>
liam@example.com
</div>
</TableCell>
<TableCell className='hidden sm:table-cell'>Sale</TableCell>
<TableCell className='hidden sm:table-cell'>
<Badge className='text-xs' variant='secondary'>
Fulfilled
</Badge>
</TableCell>
<TableCell className='hidden md:table-cell'>2023-06-23</TableCell>
<TableCell className='text-right'>$250.00</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div className='font-medium'>Olivia Smith</div>
<div className='hidden text-sm text-muted-foreground md:inline'>
olivia@example.com
</div>
</TableCell>
<TableCell className='hidden sm:table-cell'>Refund</TableCell>
<TableCell className='hidden sm:table-cell'>
<Badge className='text-xs' variant='outline'>
Declined
</Badge>
</TableCell>
<TableCell className='hidden md:table-cell'>2023-06-24</TableCell>
<TableCell className='text-right'>$150.00</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div className='font-medium'>Noah Williams</div>
<div className='hidden text-sm text-muted-foreground md:inline'>
noah@example.com
</div>
</TableCell>
<TableCell className='hidden sm:table-cell'>Subscription</TableCell>
<TableCell className='hidden sm:table-cell'>
<Badge className='text-xs' variant='secondary'>
Fulfilled
</Badge>
</TableCell>
<TableCell className='hidden md:table-cell'>2023-06-25</TableCell>
<TableCell className='text-right'>$350.00</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div className='font-medium'>Emma Brown</div>
<div className='hidden text-sm text-muted-foreground md:inline'>
emma@example.com
</div>
</TableCell>
<TableCell className='hidden sm:table-cell'>Sale</TableCell>
<TableCell className='hidden sm:table-cell'>
<Badge className='text-xs' variant='secondary'>
Fulfilled
</Badge>
</TableCell>
<TableCell className='hidden md:table-cell'>2023-06-26</TableCell>
<TableCell className='text-right'>$450.00</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div className='font-medium'>Liam Johnson</div>
<div className='hidden text-sm text-muted-foreground md:inline'>
liam@example.com
</div>
</TableCell>
<TableCell className='hidden sm:table-cell'>Sale</TableCell>
<TableCell className='hidden sm:table-cell'>
<Badge className='text-xs' variant='secondary'>
Fulfilled
</Badge>
</TableCell>
<TableCell className='hidden md:table-cell'>2023-06-23</TableCell>
<TableCell className='text-right'>$250.00</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div className='font-medium'>Liam Johnson</div>
<div className='hidden text-sm text-muted-foreground md:inline'>
liam@example.com
</div>
</TableCell>
<TableCell className='hidden sm:table-cell'>Sale</TableCell>
<TableCell className='hidden sm:table-cell'>
<Badge className='text-xs' variant='secondary'>
Fulfilled
</Badge>
</TableCell>
<TableCell className='hidden md:table-cell'>2023-06-23</TableCell>
<TableCell className='text-right'>$250.00</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div className='font-medium'>Olivia Smith</div>
<div className='hidden text-sm text-muted-foreground md:inline'>
olivia@example.com
</div>
</TableCell>
<TableCell className='hidden sm:table-cell'>Refund</TableCell>
<TableCell className='hidden sm:table-cell'>
<Badge className='text-xs' variant='outline'>
Declined
</Badge>
</TableCell>
<TableCell className='hidden md:table-cell'>2023-06-24</TableCell>
<TableCell className='text-right'>$150.00</TableCell>
</TableRow>
<TableRow>
<TableCell>
<div className='font-medium'>Emma Brown</div>
<div className='hidden text-sm text-muted-foreground md:inline'>
emma@example.com
</div>
</TableCell>
<TableCell className='hidden sm:table-cell'>Sale</TableCell>
<TableCell className='hidden sm:table-cell'>
<Badge className='text-xs' variant='secondary'>
Fulfilled
</Badge>
</TableCell>
<TableCell className='hidden md:table-cell'>2023-06-26</TableCell>
<TableCell className='text-right'>$450.00</TableCell>
</TableRow>
</TableBody>
</Table>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
<div>
<Card className='overflow-hidden' x-chunk='dashboard-05-chunk-4'>
<CardHeader className='flex flex-row items-start bg-muted/50'>
<div className='grid gap-0.5'>
<CardTitle className='flex items-center gap-2 text-lg group'>
Order Oe31b70H
<Button
size='icon'
variant='outline'
className='w-6 h-6 transition-opacity opacity-0 group-hover:opacity-100'
>
<Copy className='w-3 h-3' />
<span className='sr-only'>Copy Order ID</span>
</Button>
</CardTitle>
<CardDescription>Date: November 23, 2023</CardDescription>
</div>
<div className='flex items-center gap-1 ml-auto'>
<Button size='sm' variant='outline' className='h-8 gap-1'>
<Truck className='h-3.5 w-3.5' />
<span className='lg:sr-only xl:not-sr-only xl:whitespace-nowrap'>
Track Order
</span>
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size='icon' variant='outline' className='w-8 h-8'>
<MoreVertical className='h-3.5 w-3.5' />
<span className='sr-only'>More</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align='end'>
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuItem>Export</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>Trash</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</CardHeader>
<CardContent className='p-6 text-sm'>
<div className='grid gap-3'>
<div className='font-semibold'>Order Details</div>
<ul className='grid gap-3'>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>
Glimmer Lamps x <span>2</span>
</span>
<span>$250.00</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>
Aqua Filters x <span>1</span>
</span>
<span>$49.00</span>
</li>
</ul>
<Separator className='my-2' />
<ul className='grid gap-3'>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>Subtotal</span>
<span>$299.00</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>Shipping</span>
<span>$5.00</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>Tax</span>
<span>$25.00</span>
</li>
<li className='flex items-center justify-between font-semibold'>
<span className='text-muted-foreground'>Total</span>
<span>$329.00</span>
</li>
</ul>
</div>
<Separator className='my-4' />
<div className='grid grid-cols-2 gap-4'>
<div className='grid gap-3'>
<div className='font-semibold'>Shipping Information</div>
<address className='grid gap-0.5 not-italic text-muted-foreground'>
<span>Liam Johnson</span>
<span>1234 Main St.</span>
<span>Anytown, CA 12345</span>
</address>
</div>
<div className='grid gap-3 auto-rows-max'>
<div className='font-semibold'>Billing Information</div>
<div className='text-muted-foreground'>Same as shipping address</div>
</div>
</div>
<Separator className='my-4' />
<div className='grid gap-3'>
<div className='font-semibold'>Customer Information</div>
<dl className='grid gap-3'>
<div className='flex items-center justify-between'>
<dt className='text-muted-foreground'>Customer</dt>
<dd>Liam Johnson</dd>
</div>
<div className='flex items-center justify-between'>
<dt className='text-muted-foreground'>Email</dt>
<dd>
<a href='mailto:'>liam@acme.com</a>
</dd>
</div>
<div className='flex items-center justify-between'>
<dt className='text-muted-foreground'>Phone</dt>
<dd>
<a href='tel:'>+1 234 567 890</a>
</dd>
</div>
</dl>
</div>
<Separator className='my-4' />
<div className='grid gap-3'>
<div className='font-semibold'>Payment Information</div>
<dl className='grid gap-3'>
<div className='flex items-center justify-between'>
<dt className='flex items-center gap-1 text-muted-foreground'>
<CreditCard className='w-4 h-4' />
Visa
</dt>
<dd>**** **** **** 4532</dd>
</div>
</dl>
</div>
</CardContent>
<CardFooter className='flex flex-row items-center px-6 py-3 border-t bg-muted/50'>
<div className='text-xs text-muted-foreground'>
Updated <time dateTime='2023-11-23'>November 23, 2023</time>
</div>
<Pagination className='w-auto ml-auto mr-0'>
<PaginationContent>
<PaginationItem>
<Button size='icon' variant='outline' className='w-6 h-6'>
<ChevronLeft className='h-3.5 w-3.5' />
<span className='sr-only'>Previous Order</span>
</Button>
</PaginationItem>
<PaginationItem>
<Button size='icon' variant='outline' className='w-6 h-6'>
<ChevronRight className='h-3.5 w-3.5' />
<span className='sr-only'>Next Order</span>
</Button>
</PaginationItem>
</PaginationContent>
</Pagination>
</CardFooter>
</Card>
</div>
</div>
</LayoutContent> </LayoutContent>
</Layout> </Layout>
); );

View File

@ -39,6 +39,7 @@ export const QuotesDataTable = ({
status?: string; status?: string;
preview?: boolean; preview?: boolean;
}) => { }) => {
const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const { toast } = useToast(); const { toast } = useToast();

View File

@ -236,6 +236,14 @@ export const QuoteEdit = () => {
return () => unsubscribe(); return () => unsubscribe();
}, [watch, getValues, setValue]); }, [watch, getValues, setValue]);
const handleClose = () => {
navigate("/quotes", {
state: {
id: quoteId,
},
});
};
if (isSubmitting || isPending) { if (isSubmitting || isPending) {
return <LoadingOverlay title='Guardando cotización' />; return <LoadingOverlay title='Guardando cotización' />;
} }
@ -264,7 +272,7 @@ export const QuoteEdit = () => {
label={t("common.close")} label={t("common.close")}
variant='secondary' variant='secondary'
size='sm' size='sm'
onClick={() => navigate("/quotes")} onClick={handleClose}
/> />
<SubmitButton <SubmitButton

View File

@ -23,7 +23,7 @@ export const LayoutHeader = () => {
<UeckoLogo className='w-24' /> <UeckoLogo className='w-24' />
<span className='sr-only'>Uecko</span> <span className='sr-only'>Uecko</span>
</Link> </Link>
<Link {/*<Link
to='/home' to='/home'
className={cn( className={cn(
"transition-colors text-muted-foreground hover:text-foreground", "transition-colors text-muted-foreground hover:text-foreground",
@ -31,7 +31,7 @@ export const LayoutHeader = () => {
)} )}
> >
<Trans i18nKey='main_menu.home' /> <Trans i18nKey='main_menu.home' />
</Link> </Link>*/}
<Link <Link
to='/quotes' to='/quotes'
className={cn( className={cn(
@ -81,9 +81,9 @@ export const LayoutHeader = () => {
<Package2Icon className='w-6 h-6' /> <Package2Icon className='w-6 h-6' />
<span className='sr-only'>Uecko</span> <span className='sr-only'>Uecko</span>
</Link> </Link>
<Link to='/home' className='text-muted-foreground hover:text-foreground'> {/*<Link to='/home' className='text-muted-foreground hover:text-foreground'>
<Trans i18nKey='main_menu.home' /> <Trans i18nKey='main_menu.home' />
</Link> </Link>*/}
<Link to='/quotes' className='text-muted-foreground hover:text-foreground'> <Link to='/quotes' className='text-muted-foreground hover:text-foreground'>
<Trans i18nKey='main_menu.quotes' /> <Trans i18nKey='main_menu.quotes' />
</Link> </Link>

View File

@ -7,23 +7,17 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuLabel, DropdownMenuLabel,
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/ui"; } from "@/ui";
import { t } from "i18next"; import { t } from "i18next";
import { import { CircleUserIcon, LogOutIcon, SettingsIcon } from "lucide-react";
CircleUserIcon,
LogOutIcon,
MessageCircleQuestionIcon,
SettingsIcon,
UserIcon,
} from "lucide-react";
import { SyntheticEvent, useState } from "react"; import { SyntheticEvent, useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
export const UserButton = () => { export const UserButton = () => {
const [userMenuOpened, setUserMenuOpened] = useState(false); const [userMenuOpened, setUserMenuOpened] = useState(false);
const navigate = useNavigate(); const navigate = useNavigate();
const { openDialog: openLogoutDialog, DialogComponent: LogoutDialog } = useCustomDialog({ const { openDialog: openLogoutDialog, DialogComponent: LogoutDialog } = useCustomDialog({
title: t("main_menu.logout_dialog.title"), title: t("main_menu.logout_dialog.title"),
description: t("main_menu.logout_dialog.description"), description: t("main_menu.logout_dialog.description"),
@ -33,6 +27,7 @@ export const UserButton = () => {
navigate("/logout"); navigate("/logout");
}, },
}); });
const { data, status } = useGetProfile(); const { data, status } = useGetProfile();
const openUserMenu = (event: SyntheticEvent) => { const openUserMenu = (event: SyntheticEvent) => {
@ -64,25 +59,24 @@ export const UserButton = () => {
<DropdownMenuLabel>{t("main_menu.user.my_account")}</DropdownMenuLabel> <DropdownMenuLabel>{t("main_menu.user.my_account")}</DropdownMenuLabel>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuGroup> <DropdownMenuGroup>
<DropdownMenuItem> {/*<DropdownMenuItem>
<UserIcon className='w-4 h-4 mr-2' /> <UserIcon className='w-4 h-4 mr-2' />
<span>{t("main_menu.user.profile")}</span> <span>{t("main_menu.user.profile")}</span>
<DropdownMenuShortcut>P</DropdownMenuShortcut> <DropdownMenuShortcut>P</DropdownMenuShortcut>
</DropdownMenuItem> </DropdownMenuItem>*/}
<DropdownMenuItem> <DropdownMenuItem onSelect={() => navigate("/settings")}>
<SettingsIcon className='w-4 h-4 mr-2' /> <SettingsIcon className='w-4 h-4 mr-2' />
<span>{t("main_menu.user.settings")}</span> <span>{t("main_menu.user.settings")}</span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem> {/*<DropdownMenuItem>
<MessageCircleQuestionIcon className='w-4 h-4 mr-2' /> <MessageCircleQuestionIcon className='w-4 h-4 mr-2' />
<span>{t("main_menu.user.support")}</span> <span>{t("main_menu.user.support")}</span>
</DropdownMenuItem> </DropdownMenuItem>*/}
</DropdownMenuGroup> </DropdownMenuGroup>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItem onSelect={() => openLogoutDialog()}> <DropdownMenuItem onSelect={() => openLogoutDialog()}>
<LogOutIcon className='w-4 h-4 mr-2' /> <LogOutIcon className='w-4 h-4 mr-2' />
<span>{t("main_menu.user.logout")}</span> <span>{t("main_menu.user.logout")}</span>
<DropdownMenuShortcut>Q</DropdownMenuShortcut>
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
{LogoutDialog} {LogoutDialog}

View File

@ -24,7 +24,7 @@ export const createAxiosAuthActions = (
return { return {
success: true, success: true,
data, data,
redirectTo: "/home", redirectTo: "/quotes",
}; };
} catch (error) { } catch (error) {
return { return {

View File

@ -2,11 +2,12 @@ import { AuthActionResponse, useAuth } from "@/lib/hooks";
import { ILogin_DTO } from "@shared/contexts"; import { ILogin_DTO } from "@shared/contexts";
import { UseMutationOptions, useMutation } from "@tanstack/react-query"; import { UseMutationOptions, useMutation } from "@tanstack/react-query";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import { useToast } from "@/ui/use-toast";
import { useQueryKey } from "../useQueryKey"; import { useQueryKey } from "../useQueryKey";
export const useLogin = (params?: UseMutationOptions<AuthActionResponse, Error, ILogin_DTO>) => { export const useLogin = (params?: UseMutationOptions<AuthActionResponse, Error, ILogin_DTO>) => {
const { toast } = useToast();
const { onSuccess, onError, ...restParams } = params || {}; const { onSuccess, onError, ...restParams } = params || {};
const keys = useQueryKey(); const keys = useQueryKey();
const { login } = useAuth(); const { login } = useAuth();
@ -18,8 +19,7 @@ export const useLogin = (params?: UseMutationOptions<AuthActionResponse, Error,
onSuccess: (data, variables, context) => { onSuccess: (data, variables, context) => {
const { success, redirectTo } = data; const { success, redirectTo } = data;
if (success && redirectTo) { if (success && redirectTo) {
console.log("redirect to /home"); navigate(redirectTo || "/quotes", { replace: false });
navigate(redirectTo || "/home", { replace: false });
} }
if (onSuccess) { if (onSuccess) {
onSuccess(data, variables, context); onSuccess(data, variables, context);
@ -29,7 +29,7 @@ export const useLogin = (params?: UseMutationOptions<AuthActionResponse, Error,
const { message } = error; const { message } = error;
console.error(message); console.error(message);
toast.error(message); toast({ description: message, title: "Error" });
if (onError) { if (onError) {
onError(error, variables, context); onError(error, variables, context);