-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
=
committed
Jul 9, 2024
1 parent
8bdae8d
commit 6a9a23a
Showing
33 changed files
with
1,548 additions
and
161 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,93 @@ | ||
import {useNavigate} from "react-router-dom"; | ||
import {useMutation, useQuery} from "@tanstack/react-query"; | ||
import {getManagedRestaurant} from "@/api/get-managed-restaurant.ts"; | ||
import {signOut} from "@/api/sign-out.ts"; | ||
import {Dialog, DialogTrigger} from "@/components/ui/dialog.tsx"; | ||
import { | ||
DropdownMenu, | ||
DropdownMenuContent, DropdownMenuItem, | ||
DropdownMenuLabel, DropdownMenuSeparator, | ||
DropdownMenuTrigger | ||
} from "@/components/ui/dropdown-menu.tsx"; | ||
import {Button} from "@/components/ui/button.tsx"; | ||
import {Skeleton} from "@/components/ui/skeleton.tsx"; | ||
import {Building, ChevronDown, LogOut} from "lucide-react"; | ||
import {getProfile} from "@/api/get-profile.ts"; | ||
import {StoreProfileDialog} from "@/components/store-profile-dialog.tsx"; | ||
|
||
export function AccountMenu() { | ||
const navigate = useNavigate() | ||
|
||
const {data: profile, isLoading: isLoadingProfile} = useQuery({ | ||
queryKey: ["profile"], | ||
queryFn: getProfile, | ||
staleTime: Infinity, | ||
}) | ||
|
||
const {data: managedRestaurant, isLoading: isLoadingManagedRestaurant} = useQuery({ | ||
queryKey: ["managed-restaurant"], | ||
queryFn: getManagedRestaurant, | ||
staleTime: Infinity, | ||
}) | ||
|
||
const {mutateAsync: signOutFn, isPending: isSigningOUt} = useMutation({ | ||
mutationFn: signOut, | ||
onSuccess: () => { | ||
navigate("/sign-in", {replace: true}) | ||
} | ||
}) | ||
|
||
return ( | ||
<div>Hello world</div> | ||
<Dialog> | ||
<DropdownMenu> | ||
<DropdownMenuTrigger asChild> | ||
<Button | ||
variant={"outline"} | ||
className={"flex items-center gap-2 select-none"} | ||
> | ||
{isLoadingManagedRestaurant ? ( | ||
<Skeleton className={"h-4 w-40"}/> | ||
) : ( | ||
managedRestaurant?.name | ||
)} | ||
<ChevronDown className={"h-4 w-4"}/> | ||
</Button> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent align={"end"} className={"w-56"}> | ||
<DropdownMenuLabel className={"flex flex-col"}> | ||
{isLoadingProfile ? ( | ||
<div className={"space-y-1.5"}> | ||
<Skeleton className={"h-4 w-32"}/> | ||
<Skeleton className={"h-3 w-24"}/> | ||
</div> | ||
) : ( | ||
<> | ||
<span>{profile?.name}</span> | ||
<span className={"text-xs font-normal text-muted-foreground"}> | ||
{profile?.email} | ||
</span> | ||
</> | ||
)} | ||
</DropdownMenuLabel> | ||
|
||
<DropdownMenuSeparator/> | ||
|
||
<DialogTrigger asChild> | ||
<DropdownMenuItem> | ||
<Building className={"w-4 h-4 mr-2"}/> | ||
<span>Perfil da loja</span> | ||
</DropdownMenuItem> | ||
</DialogTrigger> | ||
|
||
<DropdownMenuItem asChild className={"text-rose-500 dark:text-rose-400"} disabled={isSigningOUt}> | ||
<button className={"w-full"} onClick={() => signOutFn()}> | ||
<LogOut className={"w-4 h-4 mr-2"}/> | ||
<span>Sair da conta</span> | ||
</button> | ||
</DropdownMenuItem> | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
<StoreProfileDialog/> | ||
</Dialog> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,15 @@ | ||
export function NavLink() { | ||
import {Link, LinkProps, useLocation} from "react-router-dom"; | ||
|
||
export type NavLinksProps = LinkProps | ||
|
||
export function NavLink(props: Readonly<NavLinksProps>) { | ||
const {pathname} = useLocation() | ||
|
||
return ( | ||
<div>Hello world</div> | ||
<Link | ||
data-current={pathname === props.to} | ||
className={"flex items-center gap-1.5 text-sm font-medium text-muted-foreground hover:text-foreground data-[current=true]:text-foreground"} | ||
{...props} | ||
/> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,30 @@ | ||
export function OrderStatus() { | ||
export type OrderStatus = | ||
| "pending" | ||
| "canceled" | ||
| "processing" | ||
| "delivering" | ||
| "delivered" | ||
|
||
interface OrderStatusProps { | ||
status: OrderStatus | ||
} | ||
|
||
const orderStatusMap: Record<OrderStatus, string> = { | ||
pending: "Pendente", | ||
canceled: "Cancelado", | ||
delivered: "Entregue", | ||
delivering: "Em entrega", | ||
processing: "Em preparo", | ||
} | ||
|
||
export function OrderStatus({status}: OrderStatusProps) { | ||
return ( | ||
<div>Hello world</div> | ||
<div className={"flex items-center gap-2"}> | ||
{status === "pending" && ( | ||
<span data-testid={"badge"} className={"h-2 w-2 rounded-full bg-slate-400"}></span> | ||
)} | ||
|
||
<span className={"font-medium text-muted-foreground"}>{orderStatusMap[status]}</span> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,48 @@ | ||
export function Pagination() { | ||
import {Button} from "@/components/ui/button.tsx"; | ||
import {ChevronLeft, ChevronRight} from "lucide-react"; | ||
|
||
export interface PaginationProps { | ||
pageIndex: number | ||
totalCount: number | ||
perPage: number | ||
onPageChange: (pageIndex: number) => Promise<void> | void | ||
} | ||
|
||
export function Pagination({pageIndex, perPage, totalCount, onPageChange}:PaginationProps) { | ||
const pages: number = Math.ceil(totalCount / perPage) || 1 | ||
return ( | ||
<div>Hello world</div> | ||
<div className={"flex items-center justify-between"}> | ||
<span className={"text-sm text-muted-foreground"}> | ||
Total de {totalCount} item(s) | ||
</span> | ||
|
||
<div className={"flex items-center gap-6 lg:gap-8"}> | ||
<div className={"text-sm font-medium"}> | ||
Página {pageIndex + 1} de {pages} | ||
</div> | ||
<div className={"flex items-center gap-2"}> | ||
|
||
<Button onClick={() => onPageChange(0)} variant={"outline"} className={"h-8 w-8 p-0"} disabled={pageIndex === 0}> | ||
<ChevronLeft className={"h-4 w-4"}/> | ||
<span className={"sr-only"}>Primeira página</span> | ||
</Button> | ||
|
||
<Button onClick={() => onPageChange(pageIndex - 1)} variant={"outline"} className={"h-8 w-8 p-0"} disabled={pageIndex === 0}> | ||
<ChevronLeft className={"h-4 w-4"}/> | ||
<span className={"sr-only"}>Página anterior</span> | ||
</Button> | ||
|
||
<Button onClick={() => onPageChange(pageIndex + 1)} variant={"outline"} className={"h-8 w-8 p-0"} disabled={pages <= pageIndex + 1}> | ||
<ChevronRight className={"h-4 w-4"}/> | ||
<span className={"sr-only"}>Próxima página</span> | ||
</Button> | ||
|
||
<Button onClick={() => onPageChange(pages - 1)} variant={"outline"} className={"h-8 w-8 p-0"} disabled={pages <= pageIndex + 1}> | ||
<ChevronRight className={"h-4 w-4"}/> | ||
<span className={"sr-only"}>Última página</span> | ||
</Button> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,111 @@ | ||
export function storeProfileDialog() { | ||
import {z} from "zod"; | ||
import {useMutation, useQuery, useQueryClient} from "@tanstack/react-query"; | ||
import {getManagedRestaurant, GetManagedRestaurantResponse} from "@/api/get-managed-restaurant.ts"; | ||
import {useForm} from "react-hook-form"; | ||
import {zodResolver} from "@hookform/resolvers/zod"; | ||
import {updateProfile} from "@/api/update-profile.ts"; | ||
import {toast} from "sonner"; | ||
import { | ||
DialogClose, | ||
DialogContent, | ||
DialogDescription, | ||
DialogFooter, | ||
DialogHeader, | ||
DialogTitle | ||
} from "@/components/ui/dialog.tsx"; | ||
import {Label} from "@/components/ui/label.tsx"; | ||
import {Input} from "@/components/ui/input.tsx"; | ||
import {Textarea} from "@/components/ui/textarea.tsx"; | ||
import {Button} from "@/components/ui/button.tsx"; | ||
|
||
const storeProfileSchema = z.object({ | ||
name: z.string().min(1), | ||
description: z.string().nullable(), | ||
}) | ||
|
||
type StoreProfileSchema = z.infer<typeof storeProfileSchema> | ||
|
||
export function StoreProfileDialog() { | ||
const queryClient = useQueryClient() | ||
|
||
const {data: managedRestaurant} = useQuery({ | ||
queryKey: ["managed-restaurant"], | ||
queryFn: getManagedRestaurant, | ||
staleTime: Infinity, | ||
}) | ||
|
||
const {register, handleSubmit, formState: {isSubmitting}} = useForm<StoreProfileSchema>({ | ||
resolver: zodResolver(storeProfileSchema), values: { | ||
name: managedRestaurant?.name ?? '', description: managedRestaurant?.description ?? '', | ||
} | ||
}) | ||
|
||
function updateManagedRestaurantCache( | ||
{name, description}: StoreProfileSchema) { | ||
const cached = queryClient.getQueryData<GetManagedRestaurantResponse>(["managed-restaurant"]) | ||
if (cached) { | ||
queryClient.setQueryData<GetManagedRestaurantResponse>(["managed-restaurant"], { | ||
...cached, | ||
name, | ||
description, | ||
}) | ||
} | ||
return {cached} | ||
} | ||
|
||
|
||
const {mutateAsync: updateProfileFn} = useMutation({ | ||
mutationFn: updateProfile, | ||
onMutate({name, description}) { | ||
const {cached} = updateManagedRestaurantCache({name, description}) | ||
return {previousRestaurant: cached} | ||
}, | ||
onError(_, _var, context) { | ||
if (context?.previousRestaurant) { | ||
updateManagedRestaurantCache(context.previousRestaurant) | ||
} | ||
} | ||
}) | ||
|
||
async function handleUpdateProfile(data: StoreProfileSchema) { | ||
try { | ||
await updateProfileFn({ | ||
name: data.name, | ||
description: data.description, | ||
}) | ||
toast.success("Perfil atualizado com sucesso!") | ||
}catch { | ||
toast.error("Falha ao atualizar o perfil, tente novamente!") | ||
} | ||
} | ||
|
||
return ( | ||
<div>Hello world</div> | ||
<DialogContent> | ||
<DialogHeader> | ||
<DialogTitle>Perfil da loja</DialogTitle> | ||
<DialogDescription>Atualize as informações do seu restaurante visíveis ao seu cliente</DialogDescription> | ||
</DialogHeader> | ||
|
||
<form onSubmit={handleSubmit(handleUpdateProfile)}> | ||
<div className={"space-y-4 py-4"}> | ||
<div className={"grid grid-cols-4 items-center gap-4"}> | ||
<Label className={"text-right"} htmlFor={"name"}>Nome</Label> | ||
<Input className={"col-span-3"} id={"name"} {...register("name")}/> | ||
</div> | ||
|
||
<div className={"grid grid-cols-4 items-center gap-4"}> | ||
<Label className={"text-right"} htmlFor={"description"}>Descrição</Label> | ||
<Textarea className={"col-span-3"} id={"description"} {...register("description")}/> | ||
</div> | ||
</div> | ||
|
||
<DialogFooter> | ||
<DialogClose asChild> | ||
<Button type={"button"} variant={"ghost"}>Cancelar</Button> | ||
</DialogClose> | ||
<Button type={"submit"} variant={"success"} disabled={isSubmitting}>Salvar</Button> | ||
</DialogFooter> | ||
</form> | ||
</DialogContent> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.