Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add editable data table to manage shelter supplies #337

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Prev Previous commit
Next Next commit
feat: add actions buttons
  • Loading branch information
Everton Pavan committed May 28, 2024
commit cd1229269693d8f6d237db409efe7f4a1690c8eb
2 changes: 1 addition & 1 deletion src/pages/ShelterSupplyTable/ShelterSupplyTable.tsx
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ const ShelterSupplyTable = () => {

return (
<Fragment>
<div className="flex flex-col h-screen items-center">
<div className="flex flex-col h-auto items-center">
<Header
title="Editar Itens"
className="bg-white [&_*]:text-zinc-800 border-b-[1px] border-b-border"
41 changes: 28 additions & 13 deletions src/pages/ShelterSupplyTable/components/data-table-row-actions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"use client"
import { Button } from "@/components/ui/button"
import { useToast } from "@/components/ui/use-toast";
// import { Row } from "@tanstack/react-table"
import { Undo } from "lucide-react"
import { Trash2, Undo } from "lucide-react"

// interface DataTableRowActionsProps<TData> {
// row: Row<TData>
@@ -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 (
<div>
<div className="hidden md:flex w-auto items-center justify-between">
<div className="hidden md:flex w-auto items-center">
<Button
variant={'ghost'}
className=""
className={!rowIsModified ? 'collapse' : 'active'}
disabled={!rowIsModified}
onClick={() => handleResetToInitialValues({
supplyId
})}
aria-label="Desfazer edições"
>
<Undo className="h-4 w-4" />

</Button>
<Button
variant={'ghost'}
className=""
onClick={() => handleDeleteSupply({
supplyId
})}
aria-label="Excluir item"
>
<Trash2 className="h-5 w-5 stroke-red-600" />
</Button>
</div>
</div>
53 changes: 18 additions & 35 deletions src/pages/ShelterSupplyTable/components/data-table-toolbar.tsx
Original file line number Diff line number Diff line change
@@ -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<TData> {
table: Table<TData>
@@ -15,25 +14,30 @@ interface DataTableToolbarProps<TData> {
export function DataTableToolbar<TData>({
table,
}: DataTableToolbarProps<TData>) {
const navigate = useNavigate();
const { shelterId } = useParams()

const isFiltered = table.getState().columnFilters.length > 0

return (
<div className="flex items-center justify-between">
<div className="flex flex-col-reverse items-start gap-y-2
md:flex-row md:flex-1 md:justify-between md:items-center "
>
<div className="flex flex-1 items-center space-x-2">
<Input
placeholder="Filtrar itens..."
value={(table.getColumn("supplyName")?.getFilterValue() as string) ?? ""}
onChange={(event) =>
table.getColumn("supplyName")?.setFilterValue(event.target.value)
}
className="h-8 w-[200px] lg:w-[400px]"
/>
<div className="flex flex-1 items-center space-x-2 relative">
<Input
placeholder="Filtrar itens..."
value={(table.getColumn("supplyName")?.getFilterValue() as string) ?? ""}
onChange={(event) => 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 && (
<Button
variant={'ghost'}
onClick={() => table.resetColumnFilters()}
className="absolute right-2 top-1/2 transform -translate-y-1/2 h-8 px-2"
>
<X className="h-4 w-4" />
</Button>
)}

{/* {table.getColumn("status") && (
<DataTableFacetedFilter
column={table.getColumn("status")}
@@ -48,28 +52,7 @@ export function DataTableToolbar<TData>({
options={priorities}
/>
)} */}
{isFiltered && (
<Button
variant="ghost"
onClick={() => table.resetColumnFilters()}
className="h-8 px-2 lg:px-3"
>
Limpar
<X className="ml-2 h-4 w-4" />
</Button>
)}
</div>


<Button
variant="ghost"
className="p-0 m-0 flex gap-2 text-blue-500 [&_svg]:stroke-blue-500 font-sm text-sm hover:text-blue-600"
onClick={() =>
navigate(`/abrigo/${shelterId}/item/cadastrar`)}
>
<PlusCircle />
Cadastrar novo item
</Button>
</div>
</div>
)
59 changes: 50 additions & 9 deletions src/pages/ShelterSupplyTable/components/data-table.tsx
Original file line number Diff line number Diff line change
@@ -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<TData, TValue> {
columns: ColumnDef<TData, TValue>[]
@@ -35,6 +39,10 @@ export function DataTable<TData extends { supply: { id: string } }, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const navigate = useNavigate();
const { shelterId } = useParams()
const { toast } = useToast();

const [rowSelection, setRowSelection] = React.useState({})
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})
@@ -69,13 +77,6 @@ export function DataTable<TData extends { supply: { id: string } }, TValue>({
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<TData extends { supply: { id: string } }, TValue>({
},
})

function handleUpdateShelterSupplies(shelterId: string, supplies: any[]) {
toast({
title: 'Suprimentos atualizados com sucesso',
});
}


return (
<div className="space-y-4">
<div className="flex items-center justify-end border-b-2">
<Button
variant="ghost"
className="p-0 m-0 flex gap-2 text-red-500 [&_svg]:stroke-red-500 font-sm text-sm hover:text-red-600"
onClick={() =>
navigate(`/abrigo/${shelterId}/item/cadastrar`)}
>
Cadastrar novo item
<PlusCircle />
</Button>
</div>

<DataTableToolbar table={table} />
<div className="rounded-md border">
<div className="fixed bottom-0 w-full left-0 bg-gray-200 p-4 z-50">
{/* <div className="fixed bottom-0 w-full left-0 bg-gray-200 p-4 z-50">
<code>{JSON.stringify(updatedRows, null, 2)}</code>
</div>
</div> */}
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
@@ -163,6 +182,28 @@ export function DataTable<TData extends { supply: { id: string } }, TValue>({
</Table>
</div>
<DataTablePagination table={table} />

<div
className="flex items-center justify-end"
>
<Button
variant={'ghost'}
className="text-red-600 hover:text-red-700"
onClick={() => {
''
}}
>
Cancelar
</Button>
<Button
className="bg-red-600 hover:bg-red-700 p-5"
disabled={updatedRows.length === 0}
onClick={() => handleUpdateShelterSupplies(shelterId!, updatedRows)}
>
Salvar
</Button>
</div>

</div>
)
}
17 changes: 10 additions & 7 deletions src/pages/ShelterSupplyTable/components/priority-cell.tsx
Original file line number Diff line number Diff line change
@@ -11,16 +11,19 @@ export const PriorityCell = ({ getValue, row, column, table }: any) => {
const initialPriority: number = getValue()
const [selectedPriority, setSelectedPriority] = useState<number>(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)
15 changes: 13 additions & 2 deletions src/pages/ShelterSupplyTable/components/quantity-cell.tsx
Original file line number Diff line number Diff line change
@@ -6,9 +6,20 @@ export const QuantityCell = ({ getValue, row, column, table }: any) => {
const initialQuantity = getValue()
const [newQuantity, setNewQuantity] = useState<number>(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)