Skip to content

Commit

Permalink
Merge pull request #6 from PS-smarthub/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
AngeloCarnevale authored Sep 19, 2024
2 parents bb08e53 + 51f1159 commit 5e543ea
Show file tree
Hide file tree
Showing 25 changed files with 1,149 additions and 58 deletions.
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npm run lint
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,36 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"prepare": "husky"
},
"dependencies": {
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
"@radix-ui/react-tooltip": "^1.1.2",
"@tanstack/react-table": "^8.20.5",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "1.0.0",
"date-fns": "^4.0.0",
"lucide-react": "^0.439.0",
"next": "14.2.9",
"next-auth": "5.0.0-beta.20",
"next-themes": "^0.3.0",
"react": "^18",
"react-day-picker": "8.10.1",
"react-dom": "^18",
"react-hook-form": "^7.53.0",
"sot": "file:",
Expand All @@ -42,6 +49,7 @@
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.9",
"husky": "^9.1.6",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
Expand Down
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 src/app/app/(main)/_components/data-table-faceted-filter.tsx
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>
)
}
Loading

0 comments on commit 5e543ea

Please sign in to comment.