-
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.
Merge pull request #6 from PS-smarthub/dev
Dev
- Loading branch information
Showing
25 changed files
with
1,149 additions
and
58 deletions.
There are no files selected for viewing
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 |
---|---|---|
@@ -0,0 +1 @@ | ||
npm run lint |
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
218 changes: 218 additions & 0 deletions
218
src/app/app/(main)/_components/create-service-order-workshop-dialog.tsx
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 |
---|---|---|
@@ -0,0 +1,218 @@ | ||
"use client" | ||
|
||
import { Button } from '@/components/ui/button' | ||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog' | ||
import { FormField, FormItem, FormLabel, FormControl, FormMessage, FormDescription, Form } from '@/components/ui/form' | ||
import { Input } from '@/components/ui/input' | ||
import { Textarea } from '@/components/ui/textarea' | ||
import { PropsWithChildren, useRef, useState } from 'react' | ||
import { useForm } from 'react-hook-form' | ||
import { zodResolver } from '@hookform/resolvers/zod' | ||
import { CreateNewWorkshopServiceOrder, createNewWorkshopServiceOrderSchema } from '../schema' | ||
import { createNewWorkshopServiceOrder } from '../action' | ||
import { toast } from '@/hooks/use-toast' | ||
import { Checkbox } from '@/components/ui/checkbox' | ||
import { useRouter } from 'next/navigation' | ||
import { CheckIcon } from '@radix-ui/react-icons' | ||
|
||
export default function CreateServiceOrderWorkshopDialog({ children }: PropsWithChildren) { | ||
const ref = useRef<HTMLDivElement>(null) | ||
const [open, setOpen] = useState(false) | ||
const form = useForm<CreateNewWorkshopServiceOrder>({ | ||
resolver: zodResolver(createNewWorkshopServiceOrderSchema), | ||
defaultValues: { | ||
automaker: '', | ||
project: '', | ||
isIntern: true, | ||
model: '', | ||
chassis: '', | ||
fleet: '', | ||
vehicleLocation: '', | ||
keyLocation: '', | ||
serviceInformations: null, | ||
deliveryDate: '', | ||
requestedBy: '' | ||
}, | ||
}) | ||
const router = useRouter() | ||
async function onSubmit(values: CreateNewWorkshopServiceOrder) { | ||
await createNewWorkshopServiceOrder(values) | ||
setOpen(false) | ||
router.refresh() | ||
toast({ | ||
description: ( | ||
<div className="w-full flex items-center"> | ||
<CheckIcon className="mr-2 w-4 h-4" /> | ||
<span className="first-letter:capitalize">Ordem de serviço da oficina criada com sucesso.</span> | ||
</div> | ||
) | ||
}) | ||
} | ||
|
||
return ( | ||
<Dialog open={open} onOpenChange={setOpen}> | ||
<DialogTrigger asChild> | ||
<div ref={ref}>{children}</div> | ||
</DialogTrigger> | ||
<DialogContent className="sm:max-w-[600px] md:max-w-[700px] lg:max-w-[800px] xl:max-w-[900px]"> | ||
<DialogHeader> | ||
<DialogTitle>Criar ordem de serviço da oficina</DialogTitle> | ||
<DialogDescription> | ||
Insira os detalhes da ordem de serviço abaixo. | ||
</DialogDescription> | ||
</DialogHeader> | ||
<Form {...form}> | ||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6"> | ||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> | ||
<FormField | ||
control={form.control} | ||
name="automaker" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Montadora</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Automaker" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="project" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Projeto</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Project" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="model" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Modelo</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Model" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="chassis" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Chassi</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Chassis" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="fleet" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Frota</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Fleet" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="vehicleLocation" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Localização do veículo</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Vehicle Location" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="keyLocation" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Localização da chave</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Key Location" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="deliveryDate" | ||
render={({ field }) => ( | ||
<FormItem className="flex flex-col"> | ||
<FormLabel>Data de entrega</FormLabel> | ||
<FormControl> | ||
<Input type="date" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
</div> | ||
<FormField | ||
control={form.control} | ||
name="isIntern" | ||
render={({ field }) => ( | ||
<FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md border p-4"> | ||
<FormControl> | ||
<Checkbox | ||
checked={field.value} | ||
onCheckedChange={field.onChange} | ||
/> | ||
</FormControl> | ||
<div className="space-y-1 leading-none"> | ||
<FormLabel> | ||
Interno | ||
</FormLabel> | ||
<FormDescription> | ||
Marque se o projeto for interno | ||
</FormDescription> | ||
</div> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="serviceInformations" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Informações do serviço</FormLabel> | ||
<FormControl> | ||
<Textarea | ||
placeholder="Service Informations" | ||
{...field} | ||
value={field.value || ''} | ||
onChange={(e) => field.onChange(e.target.value || null)} | ||
/> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<Button type="submit">Criar</Button> | ||
</form> | ||
</Form> | ||
</DialogContent> | ||
</Dialog> | ||
) | ||
} |
131 changes: 131 additions & 0 deletions
131
src/app/app/(main)/_components/data-table-faceted-filter.tsx
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 |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import * as React from "react" | ||
import { CheckIcon, PlusCircledIcon } from "@radix-ui/react-icons" | ||
import { Column } from "@tanstack/react-table" | ||
|
||
import { cn } from "@/lib/utils" | ||
import { Button } from "@/components/ui/button" | ||
import { Separator } from "@/components/ui/separator" | ||
import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover" | ||
import { CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, Command } from "@/components/ui/command" | ||
import { Badge } from "@/components/ui/badge" | ||
|
||
interface DataTableFacetedFilterProps<TData, TValue> { | ||
column?: Column<TData, TValue> | ||
title?: string | ||
options: { | ||
label: string | ||
value: string | ||
}[] | ||
} | ||
|
||
export function DataTableFacetedFilter<TData, TValue>({ | ||
column, | ||
title, | ||
options, | ||
}: DataTableFacetedFilterProps<TData, TValue>) { | ||
const facets = column?.getFacetedUniqueValues() | ||
const selectedValues = new Set(column?.getFilterValue() as string[]) | ||
|
||
return ( | ||
<Popover> | ||
<PopoverTrigger asChild> | ||
<Button variant="outline" size="sm" className="h-8 border-dashed"> | ||
<PlusCircledIcon className="mr-2 h-4 w-4" /> | ||
{title} | ||
{selectedValues?.size > 0 && ( | ||
<> | ||
<Separator orientation="vertical" className="mx-2 h-4" /> | ||
<Badge | ||
variant="secondary" | ||
className="rounded-sm px-1 font-normal lg:hidden" | ||
> | ||
{selectedValues.size} | ||
</Badge> | ||
<div className="hidden space-x-1 lg:flex"> | ||
{selectedValues.size > 2 ? ( | ||
<Badge | ||
variant="secondary" | ||
className="rounded-sm px-1 font-normal" | ||
> | ||
{selectedValues.size} selected | ||
</Badge> | ||
) : ( | ||
options | ||
.filter((option) => selectedValues.has(option.value)) | ||
.map((option) => ( | ||
<Badge | ||
variant="secondary" | ||
key={option.value} | ||
className="rounded-sm px-1 font-normal" | ||
> | ||
{option.label} | ||
</Badge> | ||
)) | ||
)} | ||
</div> | ||
</> | ||
)} | ||
</Button> | ||
</PopoverTrigger> | ||
<PopoverContent className="w-[200px] p-0 dark:bg-[#1a1a1a]" align="start"> | ||
<Command> | ||
<CommandInput placeholder={title} /> | ||
<CommandList> | ||
<CommandEmpty>No results found.</CommandEmpty> | ||
<CommandGroup> | ||
{options.map((option) => { | ||
const isSelected = selectedValues.has(option.value) | ||
return ( | ||
<CommandItem | ||
key={option.value} | ||
onSelect={() => { | ||
if (isSelected) { | ||
selectedValues.delete(option.value) | ||
} else { | ||
selectedValues.add(option.value) | ||
} | ||
const filterValues = Array.from(selectedValues) | ||
column?.setFilterValue( | ||
filterValues.length ? filterValues : undefined | ||
) | ||
}} | ||
> | ||
<div | ||
className={cn( | ||
"mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary", | ||
isSelected | ||
? "bg-primary text-primary-foreground" | ||
: "opacity-50 [&_svg]:invisible" | ||
)} | ||
> | ||
<CheckIcon className={cn("h-4 w-4")} /> | ||
</div> | ||
<span>{option.label}</span> | ||
{facets?.get(option.value) && ( | ||
<span className="ml-auto flex h-4 w-4 items-center justify-center font-mono text-xs"> | ||
{facets.get(option.value)} | ||
</span> | ||
)} | ||
</CommandItem> | ||
) | ||
})} | ||
</CommandGroup> | ||
{selectedValues.size > 0 && ( | ||
<> | ||
<CommandSeparator /> | ||
<CommandGroup> | ||
<CommandItem | ||
onSelect={() => column?.setFilterValue(undefined)} | ||
className="justify-center text-center" | ||
> | ||
Limpar filtros | ||
</CommandItem> | ||
</CommandGroup> | ||
</> | ||
)} | ||
</CommandList> | ||
</Command> | ||
</PopoverContent> | ||
</Popover> | ||
) | ||
} |
Oops, something went wrong.