From 553d87b3bebf196c4b977a89defc9ec13e6da9b1 Mon Sep 17 00:00:00 2001 From: Everton Pavan Date: Mon, 20 May 2024 16:45:44 -0300 Subject: [PATCH 1/8] feat: add supplies datatable --- package-lock.json | 154 ++++++++++++++ package.json | 10 +- src/components/ui/command.tsx | 153 ++++++++++++++ src/components/ui/dropdown-menu.tsx | 198 ++++++++++++++++++ src/components/ui/popover.tsx | 29 +++ src/components/ui/table.tsx | 117 +++++++++++ src/pages/Shelter/Shelter.tsx | 8 + .../ShelterSupplyTable/ShelterSupplyTable.tsx | 111 ++++++++++ .../ShelterSupplyTable/components/columns.tsx | 103 +++++++++ .../components/data-table-column-header.tsx | 66 ++++++ .../components/data-table-faceted-filter.tsx | 146 +++++++++++++ .../components/data-table-pagination.tsx | 91 ++++++++ .../components/data-table-toolbar.tsx | 57 +++++ .../components/data-table.tsx | 126 +++++++++++ src/pages/ShelterSupplyTable/index.ts | 3 + src/routes/Routes.tsx | 2 + 16 files changed, 1371 insertions(+), 3 deletions(-) create mode 100644 src/components/ui/command.tsx create mode 100644 src/components/ui/dropdown-menu.tsx create mode 100644 src/components/ui/popover.tsx create mode 100644 src/components/ui/table.tsx create mode 100644 src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx create mode 100644 src/pages/ShelterSupplyTable/components/columns.tsx create mode 100644 src/pages/ShelterSupplyTable/components/data-table-column-header.tsx create mode 100644 src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx create mode 100644 src/pages/ShelterSupplyTable/components/data-table-pagination.tsx create mode 100644 src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx create mode 100644 src/pages/ShelterSupplyTable/components/data-table.tsx create mode 100644 src/pages/ShelterSupplyTable/index.ts diff --git a/package-lock.json b/package-lock.json index 33731021..2a4b56b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,16 +12,20 @@ "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", + "@tanstack/react-table": "^8.17.3", "axios": "^1.6.8", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "cmdk": "^1.0.0", "date-fns": "^3.6.0", "formik": "^2.4.6", "lucide-react": "^0.378.0", @@ -1514,6 +1518,35 @@ } } }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz", + "integrity": "sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-menu": "2.0.6", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-focus-guards": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", @@ -1597,6 +1630,83 @@ } } }, + "node_modules/@radix-ui/react-menu": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz", + "integrity": "sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.7.tgz", + "integrity": "sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", @@ -2284,6 +2394,37 @@ "win32" ] }, + "node_modules/@tanstack/react-table": { + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.17.3.tgz", + "integrity": "sha512-5gwg5SvPD3lNAXPuJJz1fOCEZYk9/GeBFH3w/hCgnfyszOIzwkwgp5I7Q4MJtn0WECp84b5STQUDdmvGi8m3nA==", + "dependencies": { + "@tanstack/table-core": "8.17.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.17.3.tgz", + "integrity": "sha512-mPBodDGVL+fl6d90wUREepHa/7lhsghg2A3vFpakEhrhtbIlgNAZiMr7ccTgak5qbHqF14Fwy+W1yFWQt+WmYQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2992,6 +3133,19 @@ "node": ">=6" } }, + "node_modules/cmdk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz", + "integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==", + "dependencies": { + "@radix-ui/react-dialog": "1.0.5", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", diff --git a/package.json b/package.json index 29dd3ef1..ba308ba9 100644 --- a/package.json +++ b/package.json @@ -14,26 +14,30 @@ "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", + "@tanstack/react-table": "^8.17.3", "axios": "^1.6.8", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "cmdk": "^1.0.0", "date-fns": "^3.6.0", "formik": "^2.4.6", "lucide-react": "^0.378.0", "qs": "^6.12.1", + "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.51.4", "react-input-mask": "^2.0.4", "react-router-dom": "^6.23.0", "react-select": "^5.8.0", - "react": "^18.2.0", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", "yup": "^1.4.0" @@ -41,16 +45,16 @@ "devDependencies": { "@types/node": "^20.12.8", "@types/qs": "^6.9.15", + "@types/react": "^18.2.66", "@types/react-dom": "^18.2.22", "@types/react-input-mask": "^3.0.5", - "@types/react": "^18.2.66", "@typescript-eslint/eslint-plugin": "^7.2.0", "@typescript-eslint/parser": "^7.2.0", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.19", + "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", - "eslint": "^8.57.0", "postcss": "^8.4.38", "tailwindcss": "^3.4.3", "typescript": "^5.2.2", diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx new file mode 100644 index 00000000..dd2e876e --- /dev/null +++ b/src/components/ui/command.tsx @@ -0,0 +1,153 @@ +import * as React from "react" +import { type DialogProps } from "@radix-ui/react-dialog" +import { Command as CommandPrimitive } from "cmdk" +import { Search } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Dialog, DialogContent } from "@/components/ui/dialog" + +const Command = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Command.displayName = CommandPrimitive.displayName + +interface CommandDialogProps extends DialogProps {} + +const CommandDialog = ({ children, ...props }: CommandDialogProps) => { + return ( + + + + {children} + + + + ) +} + +const CommandInput = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ + +
+)) + +CommandInput.displayName = CommandPrimitive.Input.displayName + +const CommandList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandList.displayName = CommandPrimitive.List.displayName + +const CommandEmpty = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>((props, ref) => ( + +)) + +CommandEmpty.displayName = CommandPrimitive.Empty.displayName + +const CommandGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandGroup.displayName = CommandPrimitive.Group.displayName + +const CommandSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +CommandSeparator.displayName = CommandPrimitive.Separator.displayName + +const CommandItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandItem.displayName = CommandPrimitive.Item.displayName + +const CommandShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +CommandShortcut.displayName = "CommandShortcut" + +export { + Command, + CommandDialog, + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, + CommandShortcut, + CommandSeparator, +} diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 00000000..769ff7aa --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,198 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx new file mode 100644 index 00000000..bbba7e0e --- /dev/null +++ b/src/components/ui/popover.tsx @@ -0,0 +1,29 @@ +import * as React from "react" +import * as PopoverPrimitive from "@radix-ui/react-popover" + +import { cn } from "@/lib/utils" + +const Popover = PopoverPrimitive.Root + +const PopoverTrigger = PopoverPrimitive.Trigger + +const PopoverContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( + + + +)) +PopoverContent.displayName = PopoverPrimitive.Content.displayName + +export { Popover, PopoverTrigger, PopoverContent } diff --git a/src/components/ui/table.tsx b/src/components/ui/table.tsx new file mode 100644 index 00000000..7f3502f8 --- /dev/null +++ b/src/components/ui/table.tsx @@ -0,0 +1,117 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} diff --git a/src/pages/Shelter/Shelter.tsx b/src/pages/Shelter/Shelter.tsx index 78fea039..c9d08377 100644 --- a/src/pages/Shelter/Shelter.tsx +++ b/src/pages/Shelter/Shelter.tsx @@ -146,6 +146,14 @@ const Shelter = () => { Editar itens +
diff --git a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx new file mode 100644 index 00000000..8f9aabd5 --- /dev/null +++ b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx @@ -0,0 +1,111 @@ +import { ChevronLeft, PlusCircle } from 'lucide-react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { Fragment, useMemo, useState } from 'react'; + +import { Header, LoadingScreen, TextField } from '@/components'; +import { Button } from '@/components/ui/button'; +import { useShelter, useSupplies, useThrottle } from '@/hooks'; +import { group, normalizedCompare } from '@/lib/utils'; +// import { ShelterSupplyServices } from '@/service'; +import { useToast } from '@/components/ui/use-toast'; +// import { SupplyPriority } from '@/service/supply/types'; +import { IUseShelterDataSupply } from '@/hooks/useShelter/types'; +// import { clearCache } from '@/api/cache'; +import { IUseSuppliesData } from '@/hooks/useSupplies/types'; +import { ISupplyRowItemProps } from '../EditShelterSupply/components/SupplyRow/types'; +import { columns } from './components/columns'; +import { DataTable } from './components/data-table'; + +const ShelterSupplyTable = () => { + const navigate = useNavigate(); + const { shelterId = '-1' } = useParams(); + const { toast } = useToast(); + const { data: shelter, loading, refresh } = useShelter(shelterId); + const { data: supplies } = useSupplies(); + const [filteredSupplies, setFilteredSupplies] = useState( + [] + ); + const [searchValue, setSearchValue] = useState(''); + const [, setSearch] = useThrottle( + { + throttle: 400, + callback: (v) => { + if (v) { + setFilteredSupplies( + supplies.filter((s) => normalizedCompare(s.name, v)) + ); + } else setFilteredSupplies(supplies); + }, + }, + [supplies] + ); + const shelterSupplyData = useMemo(() => { + return (shelter?.shelterSupplies ?? []).reduce( + (prev, current) => ({ ...prev, [current.supply.id]: current }), + {} as Record + ); + }, [shelter?.shelterSupplies]); + // const supplyGroups = useMemo( + // () => + // group(filteredSupplies ?? [], 'supplyCategory.name'), + // [filteredSupplies] + // ); + + console.log(shelter.shelterSupplies) + + if (loading) return ; + + return ( + +
+
navigate(`/abrigo/${shelterId}`)} + > + + + } + /> +
+
Editar itens do abrigo
+

+ Para cada item da lista abaixo, informe a disponibilidade no abrigo + selecionado +

+ +
+ { + setSearchValue(ev.target.value); + setSearch(ev.target.value); + }} + /> +
+
+ <> + {shelterSupplyData && + + } + +
+
+
+
+ ); +}; + +export { ShelterSupplyTable }; diff --git a/src/pages/ShelterSupplyTable/components/columns.tsx b/src/pages/ShelterSupplyTable/components/columns.tsx new file mode 100644 index 00000000..771d25b3 --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/columns.tsx @@ -0,0 +1,103 @@ +"use client" + +import { ColumnDef } from "@tanstack/react-table" +// import { Badge } from "@/components/ui/badge" +import { Checkbox } from "@/components/ui/checkbox" +// import { labels, priorities, statuses } from "../data/data" +import { DataTableColumnHeader } from "./data-table-column-header" +// import { DataTableRowActions } from "./data-table-row-actions" +import { IUseShelterDataSupply } from "@/hooks/useShelter/types" + +export const columns: ColumnDef[] = [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + className="translate-y-[2px]" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + className="translate-y-[2px]" + /> + ), + enableSorting: false, + enableHiding: false, + }, + // { + // accessorKey: "id", + // header: ({ column }) => ( + // + // ), + // cell: ({ row }) =>
{row.getValue("id")}
, + // enableSorting: true, + // enableHiding: false, + // }, + { + accessorKey: "name", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + // const label = labels.find((label) => label.value === row.original.label) + + return ( +
+ {/* {label && {row.getValue("category")}} */} + + {row.getValue("name")} + +
+ ) + }, + }, + { + accessorKey: "priority", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return ( +
+ + {row.getValue("priority")} + +
+ ) + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + { + accessorKey: "quantity", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return ( +
+ + {row.getValue("quantity") ? row.getValue("quantity") : '-'} + +
+ ) + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + // { + // id: "actions", + // cell: ({ row }) => , + // }, +] diff --git a/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx b/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx new file mode 100644 index 00000000..246d12e3 --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx @@ -0,0 +1,66 @@ +import { Column } from "@tanstack/react-table" +import { cn } from "@/lib/utils" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { Button } from "@/components/ui/button" +import { EyeOff, MoveDown, MoveUp } from "lucide-react" + +interface DataTableColumnHeaderProps + extends React.HTMLAttributes { + column: Column + title: string +} + +export function DataTableColumnHeader({ + column, + title, + className, +}: DataTableColumnHeaderProps) { + if (!column.getCanSort()) { + return
{title}
+ } + + return ( +
+ + + + + + column.toggleSorting(false)}> + + Asc + + column.toggleSorting(true)}> + + Desc + + + {/* column.toggleVisibility(false)}> + + Hide + */} + + +
+ ) +} \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx b/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx new file mode 100644 index 00000000..5020e2ef --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx @@ -0,0 +1,146 @@ +import * as React from "react" +import { Column } from "@tanstack/react-table" +import { cn } from "@/lib/utils" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, +} from "@/components/ui/command" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" +import { Separator } from "@/components/ui/separator" +import { CirclePlus, SquareCheck } from "lucide-react" + +interface DataTableFacetedFilterProps { + column?: Column + title?: string + options: { + label: string + value: string + icon?: React.ComponentType<{ className?: string }> + }[] +} + +export function DataTableFacetedFilter({ + column, + title, + options, +}: DataTableFacetedFilterProps) { + const facets = column?.getFacetedUniqueValues() + const selectedValues = new Set(column?.getFilterValue() as string[]) + + return ( + + + + + + + + + No results found. + + {options.map((option) => { + const isSelected = selectedValues.has(option.value) + return ( + { + if (isSelected) { + selectedValues.delete(option.value) + } else { + selectedValues.add(option.value) + } + const filterValues = Array.from(selectedValues) + column?.setFilterValue( + filterValues.length ? filterValues : undefined + ) + }} + > +
+ +
+ {option.icon && ( + + )} + {option.label} + {facets?.get(option.value) && ( + + {facets.get(option.value)} + + )} +
+ ) + })} +
+ {selectedValues.size > 0 && ( + <> + + + column?.setFilterValue(undefined)} + className="justify-center text-center" + > + Clear filters + + + + )} +
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx b/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx new file mode 100644 index 00000000..39d92eaa --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx @@ -0,0 +1,91 @@ +import { Table } from "@tanstack/react-table" +import { Button } from "@/components/ui/button" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react" + +interface DataTablePaginationProps { + table: Table +} + +export function DataTablePagination({ + table, +}: DataTablePaginationProps) { + return ( +
+
+ {table.getFilteredSelectedRowModel().rows.length} of{" "} + {table.getFilteredRowModel().rows.length} row(s) selected. +
+
+
+

Rows per page

+ +
+
+ Page {table.getState().pagination.pageIndex + 1} of{" "} + {table.getPageCount()} +
+
+ + + + +
+
+
+ ) +} \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx b/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx new file mode 100644 index 00000000..732ef4ad --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx @@ -0,0 +1,57 @@ +"use client" + +import { Table } from "@tanstack/react-table" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +// import { priorities, statuses } from "../data/data" +// import { DataTableFacetedFilter } from "./data-table-faceted-filter" +import { X } from "lucide-react" + +interface DataTableToolbarProps { + table: Table +} + +export function DataTableToolbar({ + table, +}: DataTableToolbarProps) { + const isFiltered = table.getState().columnFilters.length > 0 + + return ( +
+
+ + table.getColumn("title")?.setFilterValue(event.target.value) + } + className="h-8 w-[150px] lg:w-[250px]" + /> + {/* {table.getColumn("status") && ( + + )} + {table.getColumn("priority") && ( + + )} */} + {isFiltered && ( + + )} +
+
+ ) +} \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/data-table.tsx b/src/pages/ShelterSupplyTable/components/data-table.tsx new file mode 100644 index 00000000..d120b56c --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/data-table.tsx @@ -0,0 +1,126 @@ +"use client" + +import * as React from "react" +import { + ColumnDef, + ColumnFiltersState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFacetedRowModel, + getFacetedUniqueValues, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table" + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" + +import { DataTablePagination } from "./data-table-pagination" +import { DataTableToolbar } from "./data-table-toolbar" + +interface DataTableProps { + columns: ColumnDef[] + data: TData[] +} + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const [rowSelection, setRowSelection] = React.useState({}) + const [columnVisibility, setColumnVisibility] = + React.useState({}) + const [columnFilters, setColumnFilters] = React.useState( + [] + ) + const [sorting, setSorting] = React.useState([]) + + const table = useReactTable({ + data, + columns, + state: { + sorting, + columnVisibility, + rowSelection, + columnFilters, + }, + enableRowSelection: true, + onRowSelectionChange: setRowSelection, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + onColumnVisibilityChange: setColumnVisibility, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFacetedRowModel: getFacetedRowModel(), + getFacetedUniqueValues: getFacetedUniqueValues(), + }) + + return ( +
+ +
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ) + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+
+ +
+ ) +} \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/index.ts b/src/pages/ShelterSupplyTable/index.ts new file mode 100644 index 00000000..e9d4b434 --- /dev/null +++ b/src/pages/ShelterSupplyTable/index.ts @@ -0,0 +1,3 @@ +import { EditShelterSupply } from './EditShelterSupply'; + +export { EditShelterSupply }; diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx index 6dd56608..6f622b29 100644 --- a/src/routes/Routes.tsx +++ b/src/routes/Routes.tsx @@ -12,6 +12,7 @@ import { AboutUs, Supporters, } from '@/pages'; +import { ShelterSupplyTable } from '@/pages/ShelterSupplyTable/ShelterSupplyTable'; const Routes = () => { return ( @@ -20,6 +21,7 @@ const Routes = () => { } /> } /> } /> + } /> } From c5f6e1136d528ab040e4f926a60b1bf90f2e6277 Mon Sep 17 00:00:00 2001 From: Everton Pavan Date: Tue, 21 May 2024 19:32:57 -0300 Subject: [PATCH 2/8] feat: add components inside each row to edit the items --- package-lock.json | 56 ++++++++ package.json | 2 + src/components/ui/toggle-group.tsx | 59 ++++++++ src/components/ui/toggle.tsx | 43 ++++++ src/lib/utils.ts | 26 ++++ .../ShelterSupplyTable/ShelterSupplyTable.tsx | 20 --- .../ShelterSupplyTable/components/columns.tsx | 136 ++++++++++-------- .../components/data-table-column-header.tsx | 7 +- .../components/data-table-faceted-filter.tsx | 2 +- .../components/data-table-pagination.tsx | 10 +- .../components/data-table-row-actions.tsx | 30 ++++ .../components/data-table-toolbar.tsx | 61 +++++--- .../components/priority-cell.tsx | 49 +++++++ 13 files changed, 391 insertions(+), 110 deletions(-) create mode 100644 src/components/ui/toggle-group.tsx create mode 100644 src/components/ui/toggle.tsx create mode 100644 src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx create mode 100644 src/pages/ShelterSupplyTable/components/priority-cell.tsx diff --git a/package-lock.json b/package-lock.json index 2a4b56b8..a5b9e65d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,8 @@ "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-toggle": "^1.0.3", + "@radix-ui/react-toggle-group": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", "@tanstack/react-table": "^8.17.3", "axios": "^1.6.8", @@ -1990,6 +1992,60 @@ } } }, + "node_modules/@radix-ui/react-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.0.3.tgz", + "integrity": "sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle-group": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.0.4.tgz", + "integrity": "sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-toggle": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tooltip": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", diff --git a/package.json b/package.json index ba308ba9..cab65d49 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,8 @@ "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-toggle": "^1.0.3", + "@radix-ui/react-toggle-group": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", "@tanstack/react-table": "^8.17.3", "axios": "^1.6.8", diff --git a/src/components/ui/toggle-group.tsx b/src/components/ui/toggle-group.tsx new file mode 100644 index 00000000..19505f9a --- /dev/null +++ b/src/components/ui/toggle-group.tsx @@ -0,0 +1,59 @@ +import * as React from "react" +import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group" +import { VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { toggleVariants } from "@/components/ui/toggle" + +const ToggleGroupContext = React.createContext< + VariantProps +>({ + size: "default", + variant: "default", +}) + +const ToggleGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, size, children, ...props }, ref) => ( + + + {children} + + +)) + +ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName + +const ToggleGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, children, variant, size, ...props }, ref) => { + const context = React.useContext(ToggleGroupContext) + + return ( + + {children} + + ) +}) + +ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName + +export { ToggleGroup, ToggleGroupItem } diff --git a/src/components/ui/toggle.tsx b/src/components/ui/toggle.tsx new file mode 100644 index 00000000..9ecac28e --- /dev/null +++ b/src/components/ui/toggle.tsx @@ -0,0 +1,43 @@ +import * as React from "react" +import * as TogglePrimitive from "@radix-ui/react-toggle" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const toggleVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground", + { + variants: { + variant: { + default: "bg-transparent", + outline: + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", + }, + size: { + default: "h-10 px-3", + sm: "h-9 px-2.5", + lg: "h-11 px-5", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +const Toggle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, size, ...props }, ref) => ( + +)) + +Toggle.displayName = TogglePrimitive.Root.displayName + +export { Toggle, toggleVariants } diff --git a/src/lib/utils.ts b/src/lib/utils.ts index dc8981ac..0ec05012 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -85,21 +85,25 @@ function getSupplyPriorityProps(priority: SupplyPriority) { return { label, className: 'bg-gray-200 text-gray-800', + initials: 'N' }; case SupplyPriority.Remaining: return { label, className: 'bg-light-green text-green-800', + initials: 'D' }; case SupplyPriority.Needing: return { label, className: 'bg-light-orange text-orange-800', + initials: 'P' }; case SupplyPriority.Urgent: return { label, className: 'bg-light-red text-red-800', + initials: 'U' }; } } @@ -180,6 +184,27 @@ function checkIsNull(v?: any | null) { return v !== null && v !== undefined; } +function separateClasses(classString: string): { bgClass: string; textClass: string } { + const classes = classString.split(' '); + let bgClass = ''; + let textClass = ''; + + classes.forEach((cls) => { + switch (true) { + case cls.startsWith('bg-'): + bgClass = cls; + break; + case cls.startsWith('text-'): + textClass = cls; + break; + default: + break; + } + }); + + return { bgClass, textClass }; +} + export { cn, getAvailabilityProps, @@ -193,4 +218,5 @@ export { removeDuplicatesByField, normalizedCompare, checkIsNull, + separateClasses }; diff --git a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx index 8f9aabd5..a59fdaba 100644 --- a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx +++ b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx @@ -51,8 +51,6 @@ const ShelterSupplyTable = () => { // [filteredSupplies] // ); - console.log(shelter.shelterSupplies) - if (loading) return ; return ( @@ -77,24 +75,6 @@ const ShelterSupplyTable = () => { Para cada item da lista abaixo, informe a disponibilidade no abrigo selecionado

- -
- { - setSearchValue(ev.target.value); - setSearch(ev.target.value); - }} - /> -
<> {shelterSupplyData && diff --git a/src/pages/ShelterSupplyTable/components/columns.tsx b/src/pages/ShelterSupplyTable/components/columns.tsx index 771d25b3..54ba33ad 100644 --- a/src/pages/ShelterSupplyTable/components/columns.tsx +++ b/src/pages/ShelterSupplyTable/components/columns.tsx @@ -1,63 +1,86 @@ "use client" import { ColumnDef } from "@tanstack/react-table" -// import { Badge } from "@/components/ui/badge" -import { Checkbox } from "@/components/ui/checkbox" -// import { labels, priorities, statuses } from "../data/data" +import { Badge } from "@/components/ui/badge" import { DataTableColumnHeader } from "./data-table-column-header" -// import { DataTableRowActions } from "./data-table-row-actions" import { IUseShelterDataSupply } from "@/hooks/useShelter/types" +import { PriorityCell } from "./priority-cell" +import { Input } from "@/components/ui/input" +import { DataTableRowActions } from "./data-table-row-actions" +// import { Checkbox } from "@/components/ui/checkbox" export const columns: ColumnDef[] = [ - { - id: "select", - header: ({ table }) => ( - table.toggleAllPageRowsSelected(!!value)} - aria-label="Select all" - className="translate-y-[2px]" - /> - ), - cell: ({ row }) => ( - row.toggleSelected(!!value)} - aria-label="Select row" - className="translate-y-[2px]" - /> - ), - enableSorting: false, - enableHiding: false, - }, // { - // accessorKey: "id", - // header: ({ column }) => ( - // + // id: "select", + // header: ({ table }) => ( + // table.toggleAllPageRowsSelected(!!value)} + // aria-label="Select all" + // className="translate-y-[2px] + // data-[state=checked]:bg-blue-500 + // " + // /> // ), - // cell: ({ row }) =>
{row.getValue("id")}
, - // enableSorting: true, + // cell: ({ row }) => ( + // row.toggleSelected(!!value)} + // aria-label="Select row" + // className="translate-y-[2px] + // data-[state=checked]:bg-blue-500 + // " + // /> + // ), + // enableSorting: false, // enableHiding: false, // }, { - accessorKey: "name", + accessorFn: (row) => row.supply.name, + id: "supplyName", header: ({ column }) => ( ), - cell: ({ row }) => { - // const label = labels.find((label) => label.value === row.original.label) - - return ( -
- {/* {label && {row.getValue("category")}} */} - - {row.getValue("name")} - -
- ) + cell: ({ row }) => ( +
+ + {row.original.supply.name} + + + {row.original.supply.supplyCategory.name} + +
+ ), + filterFn: (row, id, value) => { + const searchValue = value.toLowerCase(); + const rowValue = (row.getValue(id) as string).toLowerCase(); + return rowValue.includes(searchValue); + }, + }, + { + accessorFn: (row) => row.supply.supplyCategory.name, + id: "supplyCategoryName", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ + {row.original.supply.supplyCategory.name} + +
+ ), + filterFn: (row, id, value) => { + const searchValue = value.toLowerCase(); + const rowValue = (row.getValue(id) as string).toLowerCase(); + return rowValue.includes(searchValue); }, }, { @@ -66,13 +89,8 @@ export const columns: ColumnDef[] = [ ), cell: ({ row }) => { - return ( -
- - {row.getValue("priority")} - -
- ) + const priority: number = row.getValue("priority") + return }, filterFn: (row, id, value) => { return value.includes(row.getValue(id)) @@ -87,7 +105,11 @@ export const columns: ColumnDef[] = [ return (
- {row.getValue("quantity") ? row.getValue("quantity") : '-'} +
) @@ -96,8 +118,8 @@ export const columns: ColumnDef[] = [ return value.includes(row.getValue(id)) }, }, - // { - // id: "actions", - // cell: ({ row }) => , - // }, + { + id: "actions", + cell: ({ row }) => , + }, ] diff --git a/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx b/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx index 246d12e3..cfb3b5bf 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx @@ -8,7 +8,7 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { Button } from "@/components/ui/button" -import { EyeOff, MoveDown, MoveUp } from "lucide-react" +import { MoveDown, MoveUp } from "lucide-react" interface DataTableColumnHeaderProps extends React.HTMLAttributes { @@ -41,7 +41,6 @@ export function DataTableColumnHeader({ ) : ( <> - // )} @@ -55,10 +54,6 @@ export function DataTableColumnHeader({ Desc - {/* column.toggleVisibility(false)}> - - Hide - */}
diff --git a/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx b/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx index 5020e2ef..fa660bca 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx @@ -133,7 +133,7 @@ export function DataTableFacetedFilter({ onSelect={() => column?.setFilterValue(undefined)} className="justify-center text-center" > - Clear filters + Limpar filtros diff --git a/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx b/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx index 39d92eaa..2482de52 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx @@ -19,12 +19,12 @@ export function DataTablePagination({ return (
- {table.getFilteredSelectedRowModel().rows.length} of{" "} - {table.getFilteredRowModel().rows.length} row(s) selected. + {table.getFilteredSelectedRowModel().rows.length} de{" "} + {table.getFilteredRowModel().rows.length} suprimento(s) selecionados.
-
-

Rows per page

+
+

Suprimentos por página

- Page {table.getState().pagination.pageIndex + 1} of{" "} + Página {table.getState().pagination.pageIndex + 1} de{" "} {table.getPageCount()}
diff --git a/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx b/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx new file mode 100644 index 00000000..2affba36 --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx @@ -0,0 +1,30 @@ +"use client" + +import { Row } from "@tanstack/react-table" +import { Button } from "@/components/ui/button" +import { Save } from "lucide-react" + +interface DataTableRowActionsProps { + row: Row +} + +export function DataTableRowActions({ + row, +}: DataTableRowActionsProps) { + + return ( +
+
+ +
+
+ ) +} \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx b/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx index 732ef4ad..ad5ac8a3 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx @@ -5,7 +5,8 @@ import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" // import { priorities, statuses } from "../data/data" // import { DataTableFacetedFilter } from "./data-table-faceted-filter" -import { X } from "lucide-react" +import { PlusCircle, X } from "lucide-react" +import { useNavigate, useParams } from "react-router-dom" interface DataTableToolbarProps { table: Table @@ -14,20 +15,26 @@ interface DataTableToolbarProps { export function DataTableToolbar({ table, }: DataTableToolbarProps) { + const navigate = useNavigate(); + const { shelterId } = useParams() + const isFiltered = table.getState().columnFilters.length > 0 return (
-
- - table.getColumn("title")?.setFilterValue(event.target.value) - } - className="h-8 w-[150px] lg:w-[250px]" - /> - {/* {table.getColumn("status") && ( +
+
+ + table.getColumn("supplyName")?.setFilterValue(event.target.value) + } + className="h-8 w-[200px] lg:w-[400px]" + /> + {/* {table.getColumn("status") && ( ({ options={priorities} /> )} */} - {isFiltered && ( - - )} + {isFiltered && ( + + )} +
+ + +
) diff --git a/src/pages/ShelterSupplyTable/components/priority-cell.tsx b/src/pages/ShelterSupplyTable/components/priority-cell.tsx new file mode 100644 index 00000000..25a83294 --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/priority-cell.tsx @@ -0,0 +1,49 @@ +import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group" +import { getSupplyPriorityProps, priorityOptions } from "@/lib/utils" +import { SupplyPriority } from "@/service/supply/types" +import { useState } from "react" + +export const PriorityCell: React.FC<{ priority: number }> = ({ priority }) => { + const [selectedPriority, setSelectedPriority] = useState(priority) + return ( +
+ { + const priorityValue = Object.entries(SupplyPriority).find(([, val]) => priorityOptions[val as SupplyPriority] === value) + if (priorityValue) { + setSelectedPriority(Number(priorityValue[1])) + } + }} + > + {Object.values(SupplyPriority).filter(value => typeof value === 'number').map((value) => { + const { label: labelItem, initials: initialsItem, + // className: circleClassNameItem + } = getSupplyPriorityProps(value as SupplyPriority) + const isEqual = selectedPriority === value + // const result = separateClasses(circleClassNameItem); + // const selectedItemClassName = String(`data-[state=on]:${result.bgClass}`) + + return ( + + {initialsItem} + + ) + })} + +
+ ) +} \ No newline at end of file From cad01ea1585b956b7f4fa4ce2536e9dbcb657d95 Mon Sep 17 00:00:00 2001 From: Everton Pavan Date: Fri, 24 May 2024 17:23:13 -0300 Subject: [PATCH 3/8] feat: add logic to get the new values to update --- package-lock.json | 20 ++++++++ package.json | 2 + .../ShelterSupplyTable/ShelterSupplyTable.tsx | 43 +++------------- .../ShelterSupplyTable/components/columns.tsx | 31 ++++-------- .../components/data-table-pagination.tsx | 6 +-- .../components/data-table-row-actions.tsx | 50 +++++++++++++------ .../components/data-table.tsx | 44 +++++++++++++++- .../components/priority-cell.tsx | 44 ++++++++++------ .../components/quantity-cell.tsx | 36 +++++++++++++ 9 files changed, 184 insertions(+), 92 deletions(-) create mode 100644 src/pages/ShelterSupplyTable/components/quantity-cell.tsx diff --git a/package-lock.json b/package-lock.json index a5b9e65d..08998108 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "date-fns": "^3.6.0", "formik": "^2.4.6", "lucide-react": "^0.378.0", + "next-themes": "^0.3.0", "qs": "^6.12.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -38,6 +39,7 @@ "react-input-mask": "^2.0.4", "react-router-dom": "^6.23.0", "react-select": "^5.8.0", + "sonner": "^1.4.41", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", "yup": "^1.4.0" @@ -4644,6 +4646,15 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/next-themes": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz", + "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18", + "react-dom": "^16.8 || ^17 || ^18" + } + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -5504,6 +5515,15 @@ "node": ">=8" } }, + "node_modules/sonner": { + "version": "1.4.41", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.4.41.tgz", + "integrity": "sha512-uG511ggnnsw6gcn/X+YKkWPo5ep9il9wYi3QJxHsYe7yTZ4+cOd1wuodOUmOpFuXL+/RE3R04LczdNCDygTDgQ==", + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", diff --git a/package.json b/package.json index cab65d49..64e14857 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "date-fns": "^3.6.0", "formik": "^2.4.6", "lucide-react": "^0.378.0", + "next-themes": "^0.3.0", "qs": "^6.12.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -40,6 +41,7 @@ "react-input-mask": "^2.0.4", "react-router-dom": "^6.23.0", "react-select": "^5.8.0", + "sonner": "^1.4.41", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", "yup": "^1.4.0" diff --git a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx index a59fdaba..f610bdd4 100644 --- a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx +++ b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx @@ -1,55 +1,24 @@ -import { ChevronLeft, PlusCircle } from 'lucide-react'; +import { ChevronLeft } from 'lucide-react'; import { useNavigate, useParams } from 'react-router-dom'; -import { Fragment, useMemo, useState } from 'react'; - -import { Header, LoadingScreen, TextField } from '@/components'; +import { Fragment, useMemo } from 'react'; +import { Header, LoadingScreen } from '@/components'; import { Button } from '@/components/ui/button'; -import { useShelter, useSupplies, useThrottle } from '@/hooks'; -import { group, normalizedCompare } from '@/lib/utils'; -// import { ShelterSupplyServices } from '@/service'; -import { useToast } from '@/components/ui/use-toast'; -// import { SupplyPriority } from '@/service/supply/types'; +import { useShelter } from '@/hooks'; import { IUseShelterDataSupply } from '@/hooks/useShelter/types'; -// import { clearCache } from '@/api/cache'; -import { IUseSuppliesData } from '@/hooks/useSupplies/types'; -import { ISupplyRowItemProps } from '../EditShelterSupply/components/SupplyRow/types'; import { columns } from './components/columns'; import { DataTable } from './components/data-table'; const ShelterSupplyTable = () => { const navigate = useNavigate(); const { shelterId = '-1' } = useParams(); - const { toast } = useToast(); - const { data: shelter, loading, refresh } = useShelter(shelterId); - const { data: supplies } = useSupplies(); - const [filteredSupplies, setFilteredSupplies] = useState( - [] - ); - const [searchValue, setSearchValue] = useState(''); - const [, setSearch] = useThrottle( - { - throttle: 400, - callback: (v) => { - if (v) { - setFilteredSupplies( - supplies.filter((s) => normalizedCompare(s.name, v)) - ); - } else setFilteredSupplies(supplies); - }, - }, - [supplies] - ); + const { data: shelter, loading } = useShelter(shelterId); + const shelterSupplyData = useMemo(() => { return (shelter?.shelterSupplies ?? []).reduce( (prev, current) => ({ ...prev, [current.supply.id]: current }), {} as Record ); }, [shelter?.shelterSupplies]); - // const supplyGroups = useMemo( - // () => - // group(filteredSupplies ?? [], 'supplyCategory.name'), - // [filteredSupplies] - // ); if (loading) return ; diff --git a/src/pages/ShelterSupplyTable/components/columns.tsx b/src/pages/ShelterSupplyTable/components/columns.tsx index 54ba33ad..954ff1cb 100644 --- a/src/pages/ShelterSupplyTable/components/columns.tsx +++ b/src/pages/ShelterSupplyTable/components/columns.tsx @@ -5,8 +5,9 @@ import { Badge } from "@/components/ui/badge" import { DataTableColumnHeader } from "./data-table-column-header" import { IUseShelterDataSupply } from "@/hooks/useShelter/types" import { PriorityCell } from "./priority-cell" -import { Input } from "@/components/ui/input" -import { DataTableRowActions } from "./data-table-row-actions" +// import { DataTableRowActions } from "./data-table-row-actions" +import { QuantityCell } from "./quantity-cell" +import { DataTableRowAction } from "./data-table-row-actions" // import { Checkbox } from "@/components/ui/checkbox" export const columns: ColumnDef[] = [ @@ -88,10 +89,11 @@ export const columns: ColumnDef[] = [ header: ({ column }) => ( ), - cell: ({ row }) => { - const priority: number = row.getValue("priority") - return - }, + cell: PriorityCell, + // cell: ({ getValue, row, column, table }) => { + // const priority: number = row.getValue("priority") + // return + // }, filterFn: (row, id, value) => { return value.includes(row.getValue(id)) }, @@ -101,25 +103,14 @@ export const columns: ColumnDef[] = [ header: ({ column }) => ( ), - cell: ({ row }) => { - return ( -
- - - -
- ) - }, + cell: QuantityCell, filterFn: (row, id, value) => { return value.includes(row.getValue(id)) }, }, { id: "actions", - cell: ({ row }) => , + cell: DataTableRowAction + // cell: ({ row }) => , }, ] diff --git a/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx b/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx index 2482de52..3670ce0c 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx @@ -17,11 +17,11 @@ export function DataTablePagination({ table, }: DataTablePaginationProps) { return ( -
-
+
+ {/*
{table.getFilteredSelectedRowModel().rows.length} de{" "} {table.getFilteredRowModel().rows.length} suprimento(s) selecionados. -
+
*/}

Suprimentos por página

diff --git a/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx b/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx index 2affba36..d36a75ac 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx @@ -1,28 +1,46 @@ "use client" - -import { Row } from "@tanstack/react-table" import { Button } from "@/components/ui/button" -import { Save } from "lucide-react" +import { Undo } from "lucide-react" + +// interface DataTableRowActionsProps { +// row: Row +// } + +// export function DataTableRowActions({ +// row, +// }: DataTableRowActionsProps) { + + export function DataTableRowAction( + { getValue, row, column, table }: any) { -interface DataTableRowActionsProps { - row: Row -} + const id = row.index + const priority = getValue("priority") as number + const quantity = getValue("quantity") as number -export function DataTableRowActions({ - row, -}: DataTableRowActionsProps) { + + + // error: quando faço isso, dentro das cells priority e quantity + // the newValue not return to the initial value + function handleResetToInitialValues(values: { id: number, priority: number, quantity: number }) { + console.log({ + values + }) + + table.options.meta?.removeUpdateData(row.index, column.id, values) + } return (
-
+
diff --git a/src/pages/ShelterSupplyTable/components/data-table.tsx b/src/pages/ShelterSupplyTable/components/data-table.tsx index d120b56c..2230bc56 100644 --- a/src/pages/ShelterSupplyTable/components/data-table.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table.tsx @@ -15,7 +15,6 @@ import { getSortedRowModel, useReactTable, } from "@tanstack/react-table" - import { Table, TableBody, @@ -24,7 +23,6 @@ import { TableHeader, TableRow, } from "@/components/ui/table" - import { DataTablePagination } from "./data-table-pagination" import { DataTableToolbar } from "./data-table-toolbar" @@ -45,6 +43,12 @@ export function DataTable({ ) const [sorting, setSorting] = React.useState([]) + // const [updateData, setUpdateData] = React.useState(() => [...data]); + const [updateData, setUpdateData] = React.useState([]) + + + console.log(updateData) + const table = useReactTable({ data, columns, @@ -65,12 +69,48 @@ export function DataTable({ getSortedRowModel: getSortedRowModel(), getFacetedRowModel: getFacetedRowModel(), getFacetedUniqueValues: getFacetedUniqueValues(), + meta: { + // updateData: (rowIndex: number, columnId: string, value: string) => { + // console.log('updating data to...', value) + // setUpdateData((old) => + // old.map((row, index) => { + // if (index === rowIndex) { + // return { + // ...old[rowIndex], + // [columnId]: value, + // }; + // } + // return row; + // }) + // ); + // }, + updateData: (rowIndex: number, columnId: string, value: string) => { + setUpdateData((old) => { + const updatedData = [...old]; + if (!updatedData[rowIndex]) { + updatedData[rowIndex] = { ...data[rowIndex] }; + } + updatedData[rowIndex] = { + ...updatedData[rowIndex], + [columnId]: value, + }; + return updatedData; + }); + }, + removeUpdateData: (rowIndex: number) => { + setUpdateData((old) => old.filter((_, index) => index !== rowIndex)); + }, + } }) + return (
+
+ {JSON.stringify(updateData, null, 2)} +
{table.getHeaderGroups().map((headerGroup) => ( diff --git a/src/pages/ShelterSupplyTable/components/priority-cell.tsx b/src/pages/ShelterSupplyTable/components/priority-cell.tsx index 25a83294..3d4d2225 100644 --- a/src/pages/ShelterSupplyTable/components/priority-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/priority-cell.tsx @@ -1,10 +1,24 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group" -import { getSupplyPriorityProps, priorityOptions } from "@/lib/utils" +import { cn, getSupplyPriorityProps, priorityOptions, + // separateClasses + } from "@/lib/utils" import { SupplyPriority } from "@/service/supply/types" -import { useState } from "react" +import { useEffect, useState } from "react" + +export const PriorityCell = ({ getValue, row, column, table }: any) => { + + const initialPriority = getValue() + const [selectedPriority, setSelectedPriority] = useState(initialPriority) + + useEffect(() => { + setSelectedPriority(initialPriority) + }, [initialPriority]) + + function handleUpdatePriority(newPriority: number) { + setSelectedPriority(newPriority) + table.options.meta?.updateData(row.index, column.id, newPriority) + } -export const PriorityCell: React.FC<{ priority: number }> = ({ priority }) => { - const [selectedPriority, setSelectedPriority] = useState(priority) return (
= ({ priority }) => { onValueChange={(value) => { const priorityValue = Object.entries(SupplyPriority).find(([, val]) => priorityOptions[val as SupplyPriority] === value) if (priorityValue) { - setSelectedPriority(Number(priorityValue[1])) + handleUpdatePriority(Number(priorityValue[1])) } }} > @@ -23,21 +37,23 @@ export const PriorityCell: React.FC<{ priority: number }> = ({ priority }) => { } = getSupplyPriorityProps(value as SupplyPriority) const isEqual = selectedPriority === value // const result = separateClasses(circleClassNameItem); - // const selectedItemClassName = String(`data-[state=on]:${result.bgClass}`) + const selectedItemClassName = `data-[state=on]:bg-blue-500 data-[state=on]:text-white` + + // do not working + // const selectedItemClassName = `data-[state=on]:${result.bgClass}` return ( {initialsItem} diff --git a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx new file mode 100644 index 00000000..1d0d11d6 --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx @@ -0,0 +1,36 @@ +import { Input } from "@/components/ui/input" +import { useEffect, useState } from "react" + +export const QuantityCell = ({ getValue, row, column, table }: any) => { + + const initialQuantity = getValue() + const [newQuantity, setNewQuantity] = useState(initialQuantity) + + useEffect(() => { + setNewQuantity(initialQuantity) + }, [initialQuantity]) + + function handleUpdateQuantity(newPriorityToUpdate: number) { + setNewQuantity(newPriorityToUpdate) + table.options.meta?.updateData(row.index, column.id, newPriorityToUpdate) + } + + return ( +
+ handleUpdateQuantity(Number(e.target.value))} + value={newQuantity} + /> +

+ Anterior: + + {' '}{initialQuantity} + +

+
+ ) +} \ No newline at end of file From 68f181bb22d8b68b6f0601a73ed62e8af5b747e5 Mon Sep 17 00:00:00 2001 From: Everton Pavan Date: Mon, 27 May 2024 16:58:07 -0300 Subject: [PATCH 4/8] fix: remove update item --- .../ShelterSupplyTable/ShelterSupplyTable.tsx | 11 ++-- .../ShelterSupplyTable/components/columns.tsx | 1 + .../components/data-table-row-actions.tsx | 27 ++++++---- .../components/data-table.tsx | 54 +++++++++---------- .../components/priority-cell.tsx | 12 +++-- .../components/quantity-cell.tsx | 25 ++++++--- 6 files changed, 76 insertions(+), 54 deletions(-) diff --git a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx index f610bdd4..893cc4bf 100644 --- a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx +++ b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx @@ -4,7 +4,6 @@ import { Fragment, useMemo } from 'react'; import { Header, LoadingScreen } from '@/components'; import { Button } from '@/components/ui/button'; import { useShelter } from '@/hooks'; -import { IUseShelterDataSupply } from '@/hooks/useShelter/types'; import { columns } from './components/columns'; import { DataTable } from './components/data-table'; @@ -14,14 +13,14 @@ const ShelterSupplyTable = () => { const { data: shelter, loading } = useShelter(shelterId); const shelterSupplyData = useMemo(() => { - return (shelter?.shelterSupplies ?? []).reduce( - (prev, current) => ({ ...prev, [current.supply.id]: current }), - {} as Record - ); + return shelter?.shelterSupplies ?? []; }, [shelter?.shelterSupplies]); + if (loading) return ; + console.log(shelterSupplyData) + return (
@@ -47,7 +46,7 @@ const ShelterSupplyTable = () => {
<> {shelterSupplyData && - + }
diff --git a/src/pages/ShelterSupplyTable/components/columns.tsx b/src/pages/ShelterSupplyTable/components/columns.tsx index 954ff1cb..799a0228 100644 --- a/src/pages/ShelterSupplyTable/components/columns.tsx +++ b/src/pages/ShelterSupplyTable/components/columns.tsx @@ -83,6 +83,7 @@ export const columns: ColumnDef[] = [ const rowValue = (row.getValue(id) as string).toLowerCase(); return rowValue.includes(searchValue); }, + enableGrouping: true, }, { accessorKey: "priority", diff --git a/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx b/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx index d36a75ac..f858999b 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx @@ -1,5 +1,6 @@ "use client" import { Button } from "@/components/ui/button" +// import { Row } from "@tanstack/react-table" import { Undo } from "lucide-react" // interface DataTableRowActionsProps { @@ -11,22 +12,28 @@ import { Undo } from "lucide-react" // }: DataTableRowActionsProps) { export function DataTableRowAction( - { getValue, row, column, table }: any) { + { + // getValue, column, + row, table }: any) { - const id = row.index - const priority = getValue("priority") as number - const quantity = getValue("quantity") as number + // const id = row.index + // const priority = getValue("priority") as number + // const quantity = getValue("quantity") as number + + const supplyId = row.original.supply.id as string // error: quando faço isso, dentro das cells priority e quantity // the newValue not return to the initial value - function handleResetToInitialValues(values: { id: number, priority: number, quantity: number }) { - console.log({ - values - }) + function handleResetToInitialValues( + { supplyId }: { supplyId: string } + ) { + + console.log('handleResetToInitialValues supplyId', supplyId) + - table.options.meta?.removeUpdateData(row.index, column.id, values) + table.options.meta?.removeUpdateData(supplyId) } return ( @@ -36,7 +43,7 @@ import { Undo } from "lucide-react" variant={'ghost'} className="" onClick={() => handleResetToInitialValues({ - id, priority, quantity + supplyId })} > diff --git a/src/pages/ShelterSupplyTable/components/data-table.tsx b/src/pages/ShelterSupplyTable/components/data-table.tsx index 2230bc56..b9824da7 100644 --- a/src/pages/ShelterSupplyTable/components/data-table.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table.tsx @@ -31,7 +31,7 @@ interface DataTableProps { data: TData[] } -export function DataTable({ +export function DataTable({ columns, data, }: DataTableProps) { @@ -43,12 +43,10 @@ export function DataTable({ ) const [sorting, setSorting] = React.useState([]) - // const [updateData, setUpdateData] = React.useState(() => [...data]); +// const [updateData, setUpdateData] = React.useState([]) const [updateData, setUpdateData] = React.useState([]) - console.log(updateData) - const table = useReactTable({ data, columns, @@ -70,37 +68,35 @@ export function DataTable({ getFacetedRowModel: getFacetedRowModel(), getFacetedUniqueValues: getFacetedUniqueValues(), meta: { - // updateData: (rowIndex: number, columnId: string, value: string) => { - // console.log('updating data to...', value) - // setUpdateData((old) => - // old.map((row, index) => { - // if (index === rowIndex) { - // return { - // ...old[rowIndex], - // [columnId]: value, - // }; - // } - // return row; - // }) - // ); - // }, - updateData: (rowIndex: number, columnId: string, value: string) => { + updateData: (supplyId: string, columnId: string, value: string) => { setUpdateData((old) => { - const updatedData = [...old]; - if (!updatedData[rowIndex]) { - updatedData[rowIndex] = { ...data[rowIndex] }; + const existingIndex = old.findIndex(item => item.supply.id === supplyId); + const originalData = data.find(item => item.supply.id === supplyId); + + if (!originalData) return old; + + let updatedData: TData[]; + + if (existingIndex > -1) { + updatedData = old.map((item, index) => + index === existingIndex ? { ...item, [columnId]: value } : item + ); + } else { + updatedData = [...old, { ...originalData, [columnId]: value }]; } - updatedData[rowIndex] = { - ...updatedData[rowIndex], - [columnId]: value, - }; + + // Remove the update if it matches the original data + if (JSON.stringify(updatedData[existingIndex]) === JSON.stringify(originalData)) { + return updatedData.filter(item => item.supply.id !== supplyId); + } + return updatedData; }); }, - removeUpdateData: (rowIndex: number) => { - setUpdateData((old) => old.filter((_, index) => index !== rowIndex)); + removeUpdateData: (supplyId: string) => { + setUpdateData((old) => old.filter((updateItem) => updateItem.supply.id !== supplyId)); }, - } + }, }) diff --git a/src/pages/ShelterSupplyTable/components/priority-cell.tsx b/src/pages/ShelterSupplyTable/components/priority-cell.tsx index 3d4d2225..65c89827 100644 --- a/src/pages/ShelterSupplyTable/components/priority-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/priority-cell.tsx @@ -6,17 +6,21 @@ import { SupplyPriority } from "@/service/supply/types" import { useEffect, useState } from "react" export const PriorityCell = ({ getValue, row, column, table }: any) => { + const supplyId = row.original.supply.id as string const initialPriority = getValue() const [selectedPriority, setSelectedPriority] = useState(initialPriority) + console.log({initialPriority}) + useEffect(() => { setSelectedPriority(initialPriority) }, [initialPriority]) function handleUpdatePriority(newPriority: number) { setSelectedPriority(newPriority) - table.options.meta?.updateData(row.index, column.id, newPriority) + + table.options.meta?.updateData(row.index, column.id, newPriority, supplyId) } return ( @@ -37,8 +41,10 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { } = getSupplyPriorityProps(value as SupplyPriority) const isEqual = selectedPriority === value // const result = separateClasses(circleClassNameItem); - const selectedItemClassName = `data-[state=on]:bg-blue-500 data-[state=on]:text-white` + const selectedItemClassName = `data-[state=on]:bg-red-500 data-[state=on]:text-white` + console.log(isEqual) + // do not working // const selectedItemClassName = `data-[state=on]:${result.bgClass}` @@ -51,7 +57,7 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { variant={'outline'} className={cn( - initialPriority === value && !isEqual ? 'border-blue-400 border-2' : '', + initialPriority === value && !isEqual ? ' data-[state=off]:bg-red-500/20' : '', isEqual ? selectedItemClassName : '', )} > diff --git a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx index 1d0d11d6..e588962f 100644 --- a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx @@ -2,7 +2,7 @@ import { Input } from "@/components/ui/input" import { useEffect, useState } from "react" export const QuantityCell = ({ getValue, row, column, table }: any) => { - + const supplyId = row.original.supply.id as string const initialQuantity = getValue() const [newQuantity, setNewQuantity] = useState(initialQuantity) @@ -10,9 +10,22 @@ export const QuantityCell = ({ getValue, row, column, table }: any) => { setNewQuantity(initialQuantity) }, [initialQuantity]) - function handleUpdateQuantity(newPriorityToUpdate: number) { - setNewQuantity(newPriorityToUpdate) - table.options.meta?.updateData(row.index, column.id, newPriorityToUpdate) + function handleUpdateQuantity(newQuantityToUpdate: number) { + setNewQuantity(newQuantityToUpdate) + + console.log({ + initialQuantity, newQuantityToUpdate + }) + + if (initialQuantity === null && newQuantityToUpdate === 0) { + table.options.meta?.updateData(row.index, column.id, null) + } + + // if(initialQuantity === newQuantityToUpdate) { + // return + // } + + table.options.meta?.updateData(row.index, column.id, newQuantityToUpdate, supplyId) } return ( @@ -27,8 +40,8 @@ export const QuantityCell = ({ getValue, row, column, table }: any) => { />

Anterior: - - {' '}{initialQuantity} + + {' '}{initialQuantity ? initialQuantity : '0'}

From f1a374802e15d0c2c9206a94dfc2a3bcf25d0737 Mon Sep 17 00:00:00 2001 From: Everton Pavan Date: Tue, 28 May 2024 13:22:31 -0300 Subject: [PATCH 5/8] fix: get a updated rows into custom cells --- .../ShelterSupplyTable/ShelterSupplyTable.tsx | 3 -- .../components/data-table-row-actions.tsx | 28 +++++++++---------- .../components/data-table.tsx | 24 ++++++++++------ .../components/priority-cell.tsx | 14 ++++++---- .../components/quantity-cell.tsx | 12 ++------ 5 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx index 893cc4bf..d1174607 100644 --- a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx +++ b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx @@ -16,11 +16,8 @@ const ShelterSupplyTable = () => { return shelter?.shelterSupplies ?? []; }, [shelter?.shelterSupplies]); - if (loading) return ; - console.log(shelterSupplyData) - return (
diff --git a/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx b/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx index f858999b..5fe9edee 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx @@ -11,29 +11,27 @@ import { Undo } from "lucide-react" // row, // }: DataTableRowActionsProps) { - export function DataTableRowAction( - { - // getValue, column, - row, table }: any) { - - // const id = row.index - // const priority = getValue("priority") as number - // const quantity = getValue("quantity") as number +export function DataTableRowAction( + { + getValue, + column, + row, + table + }: any) { const supplyId = row.original.supply.id as string - + const priority = row.getValue("priority") as number + const quantity = row.getValue("quantity") as number + const priorityCollumn = table.getColumn("priority").id + const quantityCollumn = table.getColumn("quantity").id // error: quando faço isso, dentro das cells priority e quantity // the newValue not return to the initial value function handleResetToInitialValues( { supplyId }: { supplyId: string } - ) { - - console.log('handleResetToInitialValues supplyId', supplyId) - - - table.options.meta?.removeUpdateData(supplyId) + ) { + table.options.meta?.updateRowData(supplyId, priority, priorityCollumn) } return ( diff --git a/src/pages/ShelterSupplyTable/components/data-table.tsx b/src/pages/ShelterSupplyTable/components/data-table.tsx index b9824da7..7e6458ac 100644 --- a/src/pages/ShelterSupplyTable/components/data-table.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table.tsx @@ -42,10 +42,7 @@ export function DataTable({ [] ) const [sorting, setSorting] = React.useState([]) - -// const [updateData, setUpdateData] = React.useState([]) - const [updateData, setUpdateData] = React.useState([]) - + const [updatedRows, setUpdatedRows] = React.useState([]) const table = useReactTable({ data, @@ -68,8 +65,17 @@ export function DataTable({ getFacetedRowModel: getFacetedRowModel(), getFacetedUniqueValues: getFacetedUniqueValues(), meta: { - updateData: (supplyId: string, columnId: string, value: string) => { - setUpdateData((old) => { + newData: updatedRows, + updateRowData: (supplyId: string, value: string, columnId: string ) => { + setUpdatedRows((old) => { + + console.log({ + supplyId, + value, + columnId, + old, + }) + const existingIndex = old.findIndex(item => item.supply.id === supplyId); const originalData = data.find(item => item.supply.id === supplyId); @@ -93,8 +99,8 @@ export function DataTable({ return updatedData; }); }, - removeUpdateData: (supplyId: string) => { - setUpdateData((old) => old.filter((updateItem) => updateItem.supply.id !== supplyId)); + removeRowUpdate: (supplyId: string) => { + setUpdatedRows((old) => old.filter((updateItem) => updateItem.supply.id !== supplyId)); }, }, }) @@ -105,7 +111,7 @@ export function DataTable({
- {JSON.stringify(updateData, null, 2)} + {JSON.stringify(updatedRows, null, 2)}
diff --git a/src/pages/ShelterSupplyTable/components/priority-cell.tsx b/src/pages/ShelterSupplyTable/components/priority-cell.tsx index 65c89827..a5216e97 100644 --- a/src/pages/ShelterSupplyTable/components/priority-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/priority-cell.tsx @@ -8,11 +8,16 @@ import { useEffect, useState } from "react" export const PriorityCell = ({ getValue, row, column, table }: any) => { const supplyId = row.original.supply.id as string - const initialPriority = getValue() + const initialPriority: number = getValue() const [selectedPriority, setSelectedPriority] = useState(initialPriority) - console.log({initialPriority}) + const newData = table.options.meta + console.log({ + newData + }) + + // o initial nao mudou, por isso nao mudo o selected useEffect(() => { setSelectedPriority(initialPriority) }, [initialPriority]) @@ -20,7 +25,7 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { function handleUpdatePriority(newPriority: number) { setSelectedPriority(newPriority) - table.options.meta?.updateData(row.index, column.id, newPriority, supplyId) + table.options.meta?.updateRowData(supplyId, newPriority, column.id) } return ( @@ -43,8 +48,7 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { // const result = separateClasses(circleClassNameItem); const selectedItemClassName = `data-[state=on]:bg-red-500 data-[state=on]:text-white` - console.log(isEqual) - + // console.log({isEqual}) // do not working // const selectedItemClassName = `data-[state=on]:${result.bgClass}` diff --git a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx index e588962f..1f778c9a 100644 --- a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx @@ -13,19 +13,11 @@ export const QuantityCell = ({ getValue, row, column, table }: any) => { function handleUpdateQuantity(newQuantityToUpdate: number) { setNewQuantity(newQuantityToUpdate) - console.log({ - initialQuantity, newQuantityToUpdate - }) - if (initialQuantity === null && newQuantityToUpdate === 0) { - table.options.meta?.updateData(row.index, column.id, null) + table.options.meta?.updateRowData(supplyId, null, column.id) } - // if(initialQuantity === newQuantityToUpdate) { - // return - // } - - table.options.meta?.updateData(row.index, column.id, newQuantityToUpdate, supplyId) + table.options.meta?.updateRowData(supplyId, newQuantityToUpdate, column.id) } return ( From cd1229269693d8f6d237db409efe7f4a1690c8eb Mon Sep 17 00:00:00 2001 From: Everton Pavan Date: Tue, 28 May 2024 17:17:36 -0300 Subject: [PATCH 6/8] feat: add actions buttons --- .../ShelterSupplyTable/ShelterSupplyTable.tsx | 2 +- .../components/data-table-row-actions.tsx | 41 +++++++++---- .../components/data-table-toolbar.tsx | 53 ++++++----------- .../components/data-table.tsx | 59 ++++++++++++++++--- .../components/priority-cell.tsx | 17 +++--- .../components/quantity-cell.tsx | 15 ++++- 6 files changed, 120 insertions(+), 67 deletions(-) diff --git a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx index d1174607..5919cef3 100644 --- a/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx +++ b/src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx @@ -20,7 +20,7 @@ const ShelterSupplyTable = () => { return ( -
+
{ // row: Row @@ -13,39 +14,53 @@ import { Undo } from "lucide-react" export function DataTableRowAction( { - getValue, - column, + // getValue, + // column, row, table }: any) { + const { toast } = useToast(); const supplyId = row.original.supply.id as string - const priority = row.getValue("priority") as number - const quantity = row.getValue("quantity") as number - const priorityCollumn = table.getColumn("priority").id - const quantityCollumn = table.getColumn("quantity").id + const { newData } = table.options.meta + const rowIsModified = newData && newData.some((item: any) => item.supply.id === supplyId); - // error: quando faço isso, dentro das cells priority e quantity - // the newValue not return to the initial value function handleResetToInitialValues( { supplyId }: { supplyId: string } ) { - table.options.meta?.updateRowData(supplyId, priority, priorityCollumn) + table.options.meta?.removeRowUpdate(supplyId) + } + + function handleDeleteSupply(supplyId: any) { + toast({ + title: 'Suprimento excluído com sucesso', + }); } return (
-
+
+
diff --git a/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx b/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx index ad5ac8a3..07ec05ad 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx @@ -5,8 +5,7 @@ import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" // import { priorities, statuses } from "../data/data" // import { DataTableFacetedFilter } from "./data-table-faceted-filter" -import { PlusCircle, X } from "lucide-react" -import { useNavigate, useParams } from "react-router-dom" +import { X } from "lucide-react" interface DataTableToolbarProps { table: Table @@ -15,9 +14,6 @@ interface DataTableToolbarProps { export function DataTableToolbar({ table, }: DataTableToolbarProps) { - const navigate = useNavigate(); - const { shelterId } = useParams() - const isFiltered = table.getState().columnFilters.length > 0 return ( @@ -25,15 +21,23 @@ export function DataTableToolbar({
-
- - table.getColumn("supplyName")?.setFilterValue(event.target.value) - } - className="h-8 w-[200px] lg:w-[400px]" - /> +
+ table.getColumn("supplyName")?.setFilterValue(event.target.value)} + className="h-8 w-full pr-10" // Add padding to the right to avoid text overlapping with the button + /> + {isFiltered && ( + + )} + {/* {table.getColumn("status") && ( ({ options={priorities} /> )} */} - {isFiltered && ( - - )}
- - -
) diff --git a/src/pages/ShelterSupplyTable/components/data-table.tsx b/src/pages/ShelterSupplyTable/components/data-table.tsx index 7e6458ac..8c93d2ad 100644 --- a/src/pages/ShelterSupplyTable/components/data-table.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table.tsx @@ -25,6 +25,10 @@ import { } from "@/components/ui/table" import { DataTablePagination } from "./data-table-pagination" import { DataTableToolbar } from "./data-table-toolbar" +import { Button } from "@/components/ui/button" +import { useNavigate, useParams } from "react-router-dom" +import { PlusCircle } from "lucide-react" +import { useToast } from "@/components/ui/use-toast" interface DataTableProps { columns: ColumnDef[] @@ -35,6 +39,10 @@ export function DataTable({ columns, data, }: DataTableProps) { + const navigate = useNavigate(); + const { shelterId } = useParams() + const { toast } = useToast(); + const [rowSelection, setRowSelection] = React.useState({}) const [columnVisibility, setColumnVisibility] = React.useState({}) @@ -69,13 +77,6 @@ export function DataTable({ updateRowData: (supplyId: string, value: string, columnId: string ) => { setUpdatedRows((old) => { - console.log({ - supplyId, - value, - columnId, - old, - }) - const existingIndex = old.findIndex(item => item.supply.id === supplyId); const originalData = data.find(item => item.supply.id === supplyId); @@ -105,14 +106,32 @@ export function DataTable({ }, }) + function handleUpdateShelterSupplies(shelterId: string, supplies: any[]) { + toast({ + title: 'Suprimentos atualizados com sucesso', + }); + } + return (
+
+ +
+
-
+ {/*
{JSON.stringify(updatedRows, null, 2)} -
+
*/}
{table.getHeaderGroups().map((headerGroup) => ( @@ -163,6 +182,28 @@ export function DataTable({
+ +
+ + +
+
) } \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/priority-cell.tsx b/src/pages/ShelterSupplyTable/components/priority-cell.tsx index a5216e97..7e2a9b62 100644 --- a/src/pages/ShelterSupplyTable/components/priority-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/priority-cell.tsx @@ -11,16 +11,19 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { const initialPriority: number = getValue() const [selectedPriority, setSelectedPriority] = useState(initialPriority) - const newData = table.options.meta + const { newData } = table.options.meta + const rowIsModified = newData && newData.some((item: any) => item.supply.id === supplyId); - console.log({ - newData - }) + // is necessaary? + // useEffect(() => { + // setSelectedPriority(initialPriority) + // }, [initialPriority]) - // o initial nao mudou, por isso nao mudo o selected useEffect(() => { - setSelectedPriority(initialPriority) - }, [initialPriority]) + if (!rowIsModified) { + setSelectedPriority(initialPriority) + } + }, [rowIsModified, initialPriority]) function handleUpdatePriority(newPriority: number) { setSelectedPriority(newPriority) diff --git a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx index 1f778c9a..1a5b81b8 100644 --- a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx @@ -6,9 +6,20 @@ export const QuantityCell = ({ getValue, row, column, table }: any) => { const initialQuantity = getValue() const [newQuantity, setNewQuantity] = useState(initialQuantity) + const { newData } = table.options.meta + const rowIsModified = newData && newData.some((item: any) => item.supply.id === supplyId); + + // is necessaary? + // useEffect(() => { + // setNewQuantity(initialQuantity) + // }, [initialQuantity]) + useEffect(() => { - setNewQuantity(initialQuantity) - }, [initialQuantity]) + if (!rowIsModified) { + setNewQuantity(initialQuantity) + } + }, [rowIsModified, initialQuantity]) + function handleUpdateQuantity(newQuantityToUpdate: number) { setNewQuantity(newQuantityToUpdate) From 444fbe4ab0902ef438a5a75fbdfab6711e4a8156 Mon Sep 17 00:00:00 2001 From: Everton Pavan Date: Tue, 28 May 2024 21:50:55 -0300 Subject: [PATCH 7/8] feat: add filter by priority --- .../components/data-table-faceted-filter.tsx | 2 +- .../components/data-table-row-actions.tsx | 2 +- .../components/data-table-toolbar.tsx | 64 +++++++++---------- .../components/data-table.tsx | 15 ++++- .../ShelterSupplyTable/components/data.ts | 22 +++++++ .../components/priority-cell.tsx | 2 +- .../components/quantity-cell.tsx | 27 ++++---- 7 files changed, 84 insertions(+), 50 deletions(-) create mode 100644 src/pages/ShelterSupplyTable/components/data.ts diff --git a/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx b/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx index fa660bca..1d3d62da 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx @@ -54,7 +54,7 @@ export function DataTableFacetedFilter({ {selectedValues.size}
- {selectedValues.size > 2 ? ( + {selectedValues.size > 4 ? ( -
+
- )} +
+
+ table.getColumn("supplyName")?.setFilterValue(event.target.value)} + className="h-8 w-full pr-10" // Add padding to the right to avoid text overlapping with the button + /> + {isFiltered && ( + + )} +
+ +
+ {table.getColumn("priority") && ( + + )} +
- {/* {table.getColumn("status") && ( - - )} - {table.getColumn("priority") && ( - - )} */}
diff --git a/src/pages/ShelterSupplyTable/components/data-table.tsx b/src/pages/ShelterSupplyTable/components/data-table.tsx index 8c93d2ad..43c35ac5 100644 --- a/src/pages/ShelterSupplyTable/components/data-table.tsx +++ b/src/pages/ShelterSupplyTable/components/data-table.tsx @@ -35,7 +35,9 @@ interface DataTableProps { data: TData[] } -export function DataTable({ +export function DataTable({ columns, data, }: DataTableProps) { @@ -52,6 +54,8 @@ export function DataTable({ const [sorting, setSorting] = React.useState([]) const [updatedRows, setUpdatedRows] = React.useState([]) + + const table = useReactTable({ data, columns, @@ -106,7 +110,14 @@ export function DataTable({ }, }) - function handleUpdateShelterSupplies(shelterId: string, supplies: any[]) { + function handleUpdateShelterSupplies(shelterId: string, supplies: TData[]) { + + const dataToUpdate = supplies.map((v) => ({ + label: v.supply.name, + value: v.supply.id, + quantity: v.quantity, + })) + toast({ title: 'Suprimentos atualizados com sucesso', }); diff --git a/src/pages/ShelterSupplyTable/components/data.ts b/src/pages/ShelterSupplyTable/components/data.ts new file mode 100644 index 00000000..89f7b1ff --- /dev/null +++ b/src/pages/ShelterSupplyTable/components/data.ts @@ -0,0 +1,22 @@ +export const priorities = [ + { + label: "Necessita urgente", + value: '100', + // icon: ArrowDownIcon, + }, + { + label: "Precisa", + value: '10', + // icon: ArrowRightIcon, + }, + { + label: "Disponível para doação", + value: '1', + // icon: ArrowUpIcon, + }, + { + label: "Não preciso", + value: '0', + // icon: ArrowUpIcon, + } +] \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/priority-cell.tsx b/src/pages/ShelterSupplyTable/components/priority-cell.tsx index 7e2a9b62..13b3ea05 100644 --- a/src/pages/ShelterSupplyTable/components/priority-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/priority-cell.tsx @@ -64,7 +64,7 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { variant={'outline'} className={cn( - initialPriority === value && !isEqual ? ' data-[state=off]:bg-red-500/20' : '', + initialPriority === value && !isEqual ? ' data-[state=off]:border-red-400' : '', isEqual ? selectedItemClassName : '', )} > diff --git a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx index 1a5b81b8..30dd79bd 100644 --- a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx +++ b/src/pages/ShelterSupplyTable/components/quantity-cell.tsx @@ -10,9 +10,9 @@ export const QuantityCell = ({ getValue, row, column, table }: any) => { const rowIsModified = newData && newData.some((item: any) => item.supply.id === supplyId); // is necessaary? - // useEffect(() => { - // setNewQuantity(initialQuantity) - // }, [initialQuantity]) + useEffect(() => { + setNewQuantity(initialQuantity) + }, [initialQuantity]) useEffect(() => { if (!rowIsModified) { @@ -32,21 +32,24 @@ export const QuantityCell = ({ getValue, row, column, table }: any) => { } return ( -
+
handleUpdateQuantity(Number(e.target.value))} - value={newQuantity} + value={newQuantity ? newQuantity : ''} /> -

- Anterior: - - {' '}{initialQuantity ? initialQuantity : '0'} - -

+ +
+

+ Anterior: + + {' '}{initialQuantity ? initialQuantity : '0'} + +

+
) } \ No newline at end of file From 183aa73687b91c3e029b0e43015c175667fee0db Mon Sep 17 00:00:00 2001 From: Everton Pavan Date: Wed, 29 May 2024 16:26:37 -0300 Subject: [PATCH 8/8] fix: move datatable to shelter page, add edit switch button and change toggle to select --- package-lock.json | 30 +++++ package.json | 1 + .../CardAboutShelter/CardAboutShelter.tsx | 67 ++++------- .../components/InfoRow/InfoRow.tsx | 2 +- src/components/CardAboutShelter/utils.ts | 11 +- .../components/columns.tsx | 16 +-- .../components/data-table-column-header.tsx | 8 +- .../components/data-table-faceted-filter.tsx | 41 ++++--- .../components/data-table-pagination.tsx | 2 +- .../components/data-table-row-actions.tsx | 22 ++-- .../components/data-table-toolbar.tsx | 32 ++++-- .../components/data-table.tsx | 47 +++++--- .../components/data.tsx | 25 ++++ .../components/priority-cell.tsx | 53 ++++++++- .../components/quantity-cell.tsx | 6 +- .../components/utils.tsx | 14 +++ src/components/ui/switch.tsx | 27 +++++ src/hooks/useShelter/types.ts | 5 + src/lib/utils.ts | 4 +- src/pages/Shelter/Shelter.tsx | 107 +++++++++++------- .../ShelterSupplyTable/ShelterSupplyTable.tsx | 56 --------- .../ShelterSupplyTable/components/data.ts | 22 ---- src/pages/ShelterSupplyTable/index.ts | 3 - src/routes/Routes.tsx | 2 - 24 files changed, 369 insertions(+), 234 deletions(-) rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/columns.tsx (91%) rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/data-table-column-header.tsx (86%) rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/data-table-faceted-filter.tsx (76%) rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/data-table-pagination.tsx (97%) rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/data-table-row-actions.tsx (71%) rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/data-table-toolbar.tsx (64%) rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/data-table.tsx (84%) create mode 100644 src/components/ShelterSupplyEditableDataTable/components/data.tsx rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/priority-cell.tsx (58%) rename src/{pages/ShelterSupplyTable => components/ShelterSupplyEditableDataTable}/components/quantity-cell.tsx (94%) create mode 100644 src/components/ShelterSupplyEditableDataTable/components/utils.tsx create mode 100644 src/components/ui/switch.tsx delete mode 100644 src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx delete mode 100644 src/pages/ShelterSupplyTable/components/data.ts delete mode 100644 src/pages/ShelterSupplyTable/index.ts diff --git a/package-lock.json b/package-lock.json index 08998108..960d8325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toggle-group": "^1.0.4", @@ -1960,6 +1961,35 @@ } } }, + "node_modules/@radix-ui/react-switch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz", + "integrity": "sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-toast": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.1.5.tgz", diff --git a/package.json b/package.json index 64e14857..4fdd7a99 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toggle-group": "^1.0.4", diff --git a/src/components/CardAboutShelter/CardAboutShelter.tsx b/src/components/CardAboutShelter/CardAboutShelter.tsx index 34525112..781a1168 100644 --- a/src/components/CardAboutShelter/CardAboutShelter.tsx +++ b/src/components/CardAboutShelter/CardAboutShelter.tsx @@ -1,12 +1,9 @@ import { Home, UsersRound, - HandHeart, PawPrint, - Landmark, - Smartphone, - Building, - MapPinned, + DollarSign, + Phone, } from 'lucide-react'; import { Card } from '../ui/card'; @@ -22,21 +19,33 @@ const CardAboutShelter = (props: ICardAboutShelter) => { const check = (v?: string | number | boolean | null) => { return v !== undefined && v !== null; }; - const formatAddress = checkAndFormatAddress(shelter, false); + + const formatAddress = checkAndFormatAddress(shelter, true); return ( - -
Sobre o abrigo
+ +
Sobre
} label={formatAddress} /> - {Boolean(shelter.city) && ( - } label="Cidade:" value={shelter.city} /> - )} - {Boolean(shelter.zipCode) && ( - } label="CEP:" value={shelter.zipCode} /> - )} + } + label="Contato:" + value={ + check(shelter.contact) ? `${shelter.contact}` : 'Não informado' + } + clipboardButton={check(shelter.contact)} + /> {shelter.category === ShelterCategory.Shelter && ( + } + label={`Acolhendo`} + value={ + check(shelter.capacity) + ? `${shelter.shelteredPeople} de ${shelter.capacity} vagas` + : 'Não informado' + } + /> } label={ @@ -55,37 +64,11 @@ const CardAboutShelter = (props: ICardAboutShelter) => { ) } /> - } - label="Pessoas abrigadas:" - value={ - check(shelter.shelteredPeople) - ? `${shelter.shelteredPeople} pessoas` - : 'Não informado' - } - /> - } - label="Capacidade do abrigo:" - value={ - check(shelter.capacity) - ? `${shelter.capacity} pessoas` - : 'Não informado' - } - /> )} } - label="Contato:" - value={ - check(shelter.contact) ? `${shelter.contact}` : 'Não informado' - } - clipboardButton={check(shelter.contact)} - /> - } - label="Chave Pix:" + icon={} + label="Pix:" value={check(shelter.pix) ? `${shelter.pix}` : 'Não informado'} clipboardButton={check(shelter.pix)} /> diff --git a/src/components/CardAboutShelter/components/InfoRow/InfoRow.tsx b/src/components/CardAboutShelter/components/InfoRow/InfoRow.tsx index 9b70fb2a..77051e16 100644 --- a/src/components/CardAboutShelter/components/InfoRow/InfoRow.tsx +++ b/src/components/CardAboutShelter/components/InfoRow/InfoRow.tsx @@ -37,7 +37,7 @@ const InfoRow = React.forwardRef( {...rest} > {React.cloneElement(icon as any, { - className: 'min-w-5 min-h-5 w-5 h-5 stroke-muted-foreground', + className: 'min-w-5 min-h-5 w-5 h-5', })}
diff --git a/src/components/CardAboutShelter/utils.ts b/src/components/CardAboutShelter/utils.ts index 58d00b67..89f1bd9f 100644 --- a/src/components/CardAboutShelter/utils.ts +++ b/src/components/CardAboutShelter/utils.ts @@ -5,23 +5,22 @@ const formatShelterAddressFields = ( Pick > ): string => { - const { street, streetNumber, neighbourhood } = payload; - return [street, streetNumber, neighbourhood].filter(Boolean).join(', '); + const { street, streetNumber, neighbourhood} = payload; + return [street, streetNumber].filter(Boolean).join(', ').concat(' - ',[neighbourhood].filter(Boolean).join('-')); }; const checkAndFormatAddress = ( payload: Partial< Pick< IUseShelterData, - 'address' | 'city' | 'street' | 'streetNumber' | 'neighbourhood' + 'address' | 'city' | 'street' | 'streetNumber' | 'neighbourhood' | 'zipCode' > >, showCity = true ): string => { - const { address, city, ...rest } = payload; + const { city, zipCode, ...rest } = payload; return ( - address ?? - `${formatShelterAddressFields(rest)}${showCity ? ` - ${city}` : ''}` + `${formatShelterAddressFields(rest)}${showCity ? `, ${city} - RS` : ''}${zipCode ? `, ${zipCode}`: ''}` ); }; diff --git a/src/pages/ShelterSupplyTable/components/columns.tsx b/src/components/ShelterSupplyEditableDataTable/components/columns.tsx similarity index 91% rename from src/pages/ShelterSupplyTable/components/columns.tsx rename to src/components/ShelterSupplyEditableDataTable/components/columns.tsx index 799a0228..4d818784 100644 --- a/src/pages/ShelterSupplyTable/components/columns.tsx +++ b/src/components/ShelterSupplyEditableDataTable/components/columns.tsx @@ -10,6 +10,7 @@ import { QuantityCell } from "./quantity-cell" import { DataTableRowAction } from "./data-table-row-actions" // import { Checkbox } from "@/components/ui/checkbox" + export const columns: ColumnDef[] = [ // { // id: "select", @@ -47,14 +48,14 @@ export const columns: ColumnDef[] = [ ), cell: ({ row }) => (
- +

{row.original.supply.name} - - + {row.original.supply.supplyCategory.name} - +

), filterFn: (row, id, value) => { @@ -79,9 +80,10 @@ export const columns: ColumnDef[] = [
), filterFn: (row, id, value) => { - const searchValue = value.toLowerCase(); - const rowValue = (row.getValue(id) as string).toLowerCase(); - return rowValue.includes(searchValue); + // const searchValue = value + // const rowValue = (row.getValue(id) as string) + // return rowValue.includes(searchValue); + return value.includes(row.getValue(id)) }, enableGrouping: true, }, diff --git a/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx b/src/components/ShelterSupplyEditableDataTable/components/data-table-column-header.tsx similarity index 86% rename from src/pages/ShelterSupplyTable/components/data-table-column-header.tsx rename to src/components/ShelterSupplyEditableDataTable/components/data-table-column-header.tsx index cfb3b5bf..905b92c0 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-column-header.tsx +++ b/src/components/ShelterSupplyEditableDataTable/components/data-table-column-header.tsx @@ -8,7 +8,7 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { Button } from "@/components/ui/button" -import { MoveDown, MoveUp } from "lucide-react" +import { ArrowDownUpIcon, MoveDown, MoveUp } from "lucide-react" interface DataTableColumnHeaderProps extends React.HTMLAttributes { @@ -36,11 +36,11 @@ export function DataTableColumnHeader({ > {title} {column.getIsSorted() === "desc" ? ( - + ) : column.getIsSorted() === "asc" ? ( - + ) : ( - <> + )} diff --git a/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx b/src/components/ShelterSupplyEditableDataTable/components/data-table-faceted-filter.tsx similarity index 76% rename from src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx rename to src/components/ShelterSupplyEditableDataTable/components/data-table-faceted-filter.tsx index 1d3d62da..a6cf3f92 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-faceted-filter.tsx +++ b/src/components/ShelterSupplyEditableDataTable/components/data-table-faceted-filter.tsx @@ -18,14 +18,16 @@ import { PopoverTrigger, } from "@/components/ui/popover" import { Separator } from "@/components/ui/separator" -import { CirclePlus, SquareCheck } from "lucide-react" +import { Check, CirclePlus } from "lucide-react" +import { getColorClass } from "./utils" + interface DataTableFacetedFilterProps { column?: Column title?: string options: { label: string - value: string + value: string | number icon?: React.ComponentType<{ className?: string }> }[] } @@ -36,7 +38,17 @@ export function DataTableFacetedFilter({ options, }: DataTableFacetedFilterProps) { const facets = column?.getFacetedUniqueValues() - const selectedValues = new Set(column?.getFilterValue() as string[]) + const selectedValues = new Set(column?.getFilterValue() as Array) + + // Sort options based on the facet values in descending order + const sortedOptions = React.useMemo(() => { + return options.sort((a, b) => { + const aValue = facets?.get(a.value) ?? 0; + const bValue = facets?.get(b.value) ?? 0; + // Reverse the comparison to sort in descending order + return bValue - aValue; + }); + }, [options, facets]); return ( @@ -44,7 +56,7 @@ export function DataTableFacetedFilter({ - + - No results found. + Nenhum resultado encontrado. - {options.map((option) => { + {/* {options.map((option) => { */} + {sortedOptions.map((option) => { const isSelected = selectedValues.has(option.value) + const colorPriorityClass = title === "Prioridade" ? getColorClass(option.value) : ""; return ( ({ className={cn( "mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary", isSelected - ? "bg-primary text-primary-foreground" + ? "bg-primary text-primary-foreground" : "opacity-50 [&_svg]:invisible" )} > - +
{option.icon && ( - + )} {option.label} {facets?.get(option.value) && ( @@ -143,4 +158,4 @@ export function DataTableFacetedFilter({ ) -} \ No newline at end of file +} diff --git a/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx b/src/components/ShelterSupplyEditableDataTable/components/data-table-pagination.tsx similarity index 97% rename from src/pages/ShelterSupplyTable/components/data-table-pagination.tsx rename to src/components/ShelterSupplyEditableDataTable/components/data-table-pagination.tsx index 3670ce0c..afe24bea 100644 --- a/src/pages/ShelterSupplyTable/components/data-table-pagination.tsx +++ b/src/components/ShelterSupplyEditableDataTable/components/data-table-pagination.tsx @@ -24,7 +24,7 @@ export function DataTablePagination({
*/}
-

Suprimentos por página

+

Itens por página

+
{table.getHeaderGroups().map((headerGroup) => ( @@ -192,17 +201,29 @@ export function DataTable
- - +
+
+ +
+ + +
diff --git a/src/components/ShelterSupplyEditableDataTable/components/data.tsx b/src/components/ShelterSupplyEditableDataTable/components/data.tsx new file mode 100644 index 00000000..b4fcb933 --- /dev/null +++ b/src/components/ShelterSupplyEditableDataTable/components/data.tsx @@ -0,0 +1,25 @@ +import { CircleIcon } from "lucide-react" + + +export const priorities = [ + { + label: "Necessita urgente", + value: 100, + icon: CircleIcon + }, + { + label: "Precisa", + value: 10, + icon: CircleIcon + }, + { + label: "Disponível para doação", + value: 1, + icon: CircleIcon + }, + { + label: "Não preciso", + value: 0, + icon: CircleIcon + } +] \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/priority-cell.tsx b/src/components/ShelterSupplyEditableDataTable/components/priority-cell.tsx similarity index 58% rename from src/pages/ShelterSupplyTable/components/priority-cell.tsx rename to src/components/ShelterSupplyEditableDataTable/components/priority-cell.tsx index 13b3ea05..e217ddf4 100644 --- a/src/pages/ShelterSupplyTable/components/priority-cell.tsx +++ b/src/components/ShelterSupplyEditableDataTable/components/priority-cell.tsx @@ -1,9 +1,20 @@ -import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group" +// import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group" +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + // SelectLabel, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" import { cn, getSupplyPriorityProps, priorityOptions, // separateClasses } from "@/lib/utils" import { SupplyPriority } from "@/service/supply/types" import { useEffect, useState } from "react" +import { CircleIcon } from "lucide-react" +import { getColorClass } from "./utils" export const PriorityCell = ({ getValue, row, column, table }: any) => { const supplyId = row.original.supply.id as string @@ -32,8 +43,9 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { } return ( -
- + {/* Maybe show this component to mobile devices */} + {/* { @@ -50,7 +62,6 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { const isEqual = selectedPriority === value // const result = separateClasses(circleClassNameItem); const selectedItemClassName = `data-[state=on]:bg-red-500 data-[state=on]:text-white` - // console.log({isEqual}) // do not working // const selectedItemClassName = `data-[state=on]:${result.bgClass}` @@ -64,7 +75,7 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { variant={'outline'} className={cn( - initialPriority === value && !isEqual ? ' data-[state=off]:border-red-400' : '', + initialPriority === value && !isEqual ? ' data-[state=off]:border-red-400 text-gray-400' : '', isEqual ? selectedItemClassName : '', )} > @@ -72,7 +83,37 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => { ) })} - + */} + +
) } \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx b/src/components/ShelterSupplyEditableDataTable/components/quantity-cell.tsx similarity index 94% rename from src/pages/ShelterSupplyTable/components/quantity-cell.tsx rename to src/components/ShelterSupplyEditableDataTable/components/quantity-cell.tsx index 30dd79bd..bb6143f1 100644 --- a/src/pages/ShelterSupplyTable/components/quantity-cell.tsx +++ b/src/components/ShelterSupplyEditableDataTable/components/quantity-cell.tsx @@ -42,14 +42,14 @@ export const QuantityCell = ({ getValue, row, column, table }: any) => { value={newQuantity ? newQuantity : ''} /> -
-

+ {/*

+

Anterior: {' '}{initialQuantity ? initialQuantity : '0'}

-
+
*/}
) } \ No newline at end of file diff --git a/src/components/ShelterSupplyEditableDataTable/components/utils.tsx b/src/components/ShelterSupplyEditableDataTable/components/utils.tsx new file mode 100644 index 00000000..c86af4c6 --- /dev/null +++ b/src/components/ShelterSupplyEditableDataTable/components/utils.tsx @@ -0,0 +1,14 @@ +export const getColorClass = (value: string | number) => { + switch (value) { + case 100: + return "fill-red-300 stroke-red-300"; + case 10: + return "fill-orange-300 stroke-orange-300"; + case 1: + return "fill-green-300 stroke-green-300"; + case 0: + return "fill-slate-300 stroke-slate-300"; + default: + return "fill-transparent"; + } +}; diff --git a/src/components/ui/switch.tsx b/src/components/ui/switch.tsx new file mode 100644 index 00000000..aa58baa2 --- /dev/null +++ b/src/components/ui/switch.tsx @@ -0,0 +1,27 @@ +import * as React from "react" +import * as SwitchPrimitives from "@radix-ui/react-switch" + +import { cn } from "@/lib/utils" + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +Switch.displayName = SwitchPrimitives.Root.displayName + +export { Switch } diff --git a/src/hooks/useShelter/types.ts b/src/hooks/useShelter/types.ts index 22c3bd67..fea994a6 100644 --- a/src/hooks/useShelter/types.ts +++ b/src/hooks/useShelter/types.ts @@ -3,6 +3,11 @@ export enum ShelterCategory { DistributionCenter = 'DistributionCenter', } +export enum ShelterCategoryName { + Shelter = 'Abrigo', + DistributionCenter = 'Centro de Distribuição', +} + export interface IUseShelterData { id: string; name: string; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 0ec05012..3d1381cc 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -56,12 +56,12 @@ function getAvailabilityProps(props: { } else if (capacity && (shelteredPeople || shelteredPeople === 0)) { if (shelteredPeople < capacity) return { - availability: 'Abrigo disponível', + availability: 'disponível', className: 'text-green-600', }; else return { - availability: 'Abrigo lotado', + availability: 'lotado', className: 'text-red-400', }; } else diff --git a/src/pages/Shelter/Shelter.tsx b/src/pages/Shelter/Shelter.tsx index c9d08377..45d5b27e 100644 --- a/src/pages/Shelter/Shelter.tsx +++ b/src/pages/Shelter/Shelter.tsx @@ -11,7 +11,10 @@ import { } from '@/components'; import { useShelter } from '@/hooks'; import { IShelterAvailabilityProps } from '@/pages/Home/components/ShelterListItem/types'; -import { cn, getAvailabilityProps, group } from '@/lib/utils'; +import { + cn, getAvailabilityProps, + group +} from '@/lib/utils'; import { Button } from '@/components/ui/button'; import { ShelterCategoryItems } from './components'; import { @@ -23,7 +26,11 @@ import { VerifiedBadge } from '@/components/VerifiedBadge/VerifiedBadge.tsx'; import { ShelterSupplyServices } from '@/service'; import { useToast } from '@/components/ui/use-toast'; import { clearCache } from '@/api/cache'; -import { ShelterCategory } from '@/hooks/useShelter/types'; +import { ShelterCategory, ShelterCategoryName } from '@/hooks/useShelter/types'; +import { DataTable } from '../../components/ShelterSupplyEditableDataTable/components/data-table'; +import { columns } from '../../components/ShelterSupplyEditableDataTable/components/columns'; +import { Label } from '@/components/ui/label'; +import { Switch } from '@/components/ui/switch'; const Shelter = () => { const params = useParams(); @@ -46,6 +53,7 @@ const Shelter = () => { })), })); }, [shelter?.shelterSupplies]); + const { availability, className: availabilityClassName } = useMemo( () => @@ -90,6 +98,11 @@ const Shelter = () => { }); }, [refresh, selectedTags, shelterId, toast]); + const [showEditableTableData, setShowEditableTableData] = useState(false) + const shelterSupplyData = useMemo(() => { + return shelter?.shelterSupplies ?? []; + }, [shelter?.shelterSupplies]); + if (loading) return ; return ( @@ -107,57 +120,77 @@ const Shelter = () => { } /> -
-
-

- {shelter.name} -

- {shelter.verified && } -
-
+
+
+
+ {ShelterCategoryName[shelter.category]} + {shelter.verified && } +

{availability}

+
+
+

+ {shelter.name} +

-
+
-
+ {shelter.updatedAt && ( +
+ + Atualizado em {format(shelter.updatedAt, 'dd/MM/yyyy HH:mm')} + +
+ )} +

Itens do abrigo

-
- - + + */}
-
- {shelterCategories.map((categoryProps, idx) => ( +
+ {!showEditableTableData && shelterCategories.map((categoryProps, idx) => ( { {...categoryProps} /> ))} + {shelterSupplyData && showEditableTableData && + + }
- {shelter.updatedAt && ( -
- - Atualizado em {format(shelter.updatedAt, 'dd/MM/yyyy HH:mm')} - -
- )} + +
- } - /> -
-
Editar itens do abrigo
-

- Para cada item da lista abaixo, informe a disponibilidade no abrigo - selecionado -

-
- <> - {shelterSupplyData && - - } - -
-
-
- - ); -}; - -export { ShelterSupplyTable }; diff --git a/src/pages/ShelterSupplyTable/components/data.ts b/src/pages/ShelterSupplyTable/components/data.ts deleted file mode 100644 index 89f7b1ff..00000000 --- a/src/pages/ShelterSupplyTable/components/data.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const priorities = [ - { - label: "Necessita urgente", - value: '100', - // icon: ArrowDownIcon, - }, - { - label: "Precisa", - value: '10', - // icon: ArrowRightIcon, - }, - { - label: "Disponível para doação", - value: '1', - // icon: ArrowUpIcon, - }, - { - label: "Não preciso", - value: '0', - // icon: ArrowUpIcon, - } -] \ No newline at end of file diff --git a/src/pages/ShelterSupplyTable/index.ts b/src/pages/ShelterSupplyTable/index.ts deleted file mode 100644 index e9d4b434..00000000 --- a/src/pages/ShelterSupplyTable/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { EditShelterSupply } from './EditShelterSupply'; - -export { EditShelterSupply }; diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx index 6f622b29..6dd56608 100644 --- a/src/routes/Routes.tsx +++ b/src/routes/Routes.tsx @@ -12,7 +12,6 @@ import { AboutUs, Supporters, } from '@/pages'; -import { ShelterSupplyTable } from '@/pages/ShelterSupplyTable/ShelterSupplyTable'; const Routes = () => { return ( @@ -21,7 +20,6 @@ const Routes = () => { } /> } /> } /> - } /> }