-
- }
- mode="ListView"
- active={timesheetNavigator === 'ListView'}
- onClick={() => setTimesheetNavigator('ListView')}
- t={t}
- />
- }
- mode="CalendarView"
- active={timesheetNavigator === 'CalendarView'}
- onClick={() => setTimesheetNavigator('CalendarView')}
- t={t}
- />
-
-
-
-
setSearch(v.target.value)}
- role="searchbox"
- aria-label="Search timesheet"
- type="search"
- name="timesheet-search"
- id="timesheet-search"
- className="!h-[2.2rem] w-full bg-transparent focus:border-transparent focus:ring-2 focus:ring-transparent placeholder-gray-500 placeholder:font-medium shadow-sm outline-none"
- placeholder={t('common.SEARCH')}
- />
+
+
+ }
+ mode="ListView"
+ active={timesheetNavigator === 'ListView'}
+ onClick={() => setTimesheetNavigator('ListView')}
+ t={t}
+ />
+ }
+ mode="CalendarView"
+ active={timesheetNavigator === 'CalendarView'}
+ onClick={() => setTimesheetNavigator('CalendarView')}
+ t={t}
+ />
+
+
+
+ setSearch(v.target.value)}
+ role="searchbox"
+ aria-label="Search timesheet"
+ type="search"
+ name="timesheet-search"
+ id="timesheet-search"
+ className="!h-[2.2rem] w-full bg-transparent focus:border-transparent focus:ring-2 focus:ring-transparent placeholder-gray-500 placeholder:font-medium shadow-sm outline-none"
+ placeholder={t('common.SEARCH')}
+ />
+
-
- {/*
*/}
-
+
-
- {timesheetNavigator === 'ListView' ? (
-
- ) : (
-
- )}
-
+
+
+ }
+ >
+
+
+ {/* */}
+
+ {timesheetNavigator === 'ListView' ? (
+
+ ) : (
+
+ )}
diff --git a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx
index 01bc391b0..52fb005b5 100644
--- a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx
+++ b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx
@@ -1,573 +1,545 @@
-"use client"
+'use client';
-import * as React from "react"
+import * as React from 'react';
import {
- ColumnDef,
- ColumnFiltersState,
- SortingState,
- VisibilityState, getCoreRowModel,
- getFilteredRowModel,
- getPaginationRowModel,
- getSortedRowModel,
- useReactTable
-} from "@tanstack/react-table"
-import { ArrowUpDownIcon, MoreHorizontal } from "lucide-react"
-import { Button } from "@components/ui/button"
+ ColumnDef,
+ ColumnFiltersState,
+ SortingState,
+ VisibilityState,
+ getCoreRowModel,
+ getFilteredRowModel,
+ getPaginationRowModel,
+ getSortedRowModel,
+ useReactTable
+} from '@tanstack/react-table';
+import { ArrowUpDownIcon, MoreHorizontal } from 'lucide-react';
+import { Button } from '@components/ui/button';
import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuPortal,
- DropdownMenuSeparator,
- DropdownMenuSub,
- DropdownMenuSubContent,
- DropdownMenuSubTrigger,
- DropdownMenuTrigger,
-} from "@components/ui/dropdown-menu"
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuPortal,
+ DropdownMenuSeparator,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuTrigger
+} from '@components/ui/dropdown-menu';
import {
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectLabel,
- SelectTrigger,
- SelectValue,
-} from "@components/ui/select"
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectTrigger,
+ SelectValue
+} from '@components/ui/select';
import {
- MdKeyboardDoubleArrowLeft,
- MdKeyboardDoubleArrowRight,
- MdKeyboardArrowLeft,
- MdKeyboardArrowRight
-} from "react-icons/md"
-import { ConfirmStatusChange, StatusBadge, statusOptions, dataSourceTimeSheet, TimeSheet } from "."
-import { useModal, useTimelogFilterOptions } from "@app/hooks"
-import { Checkbox } from "@components/ui/checkbox"
+ MdKeyboardDoubleArrowLeft,
+ MdKeyboardDoubleArrowRight,
+ MdKeyboardArrowLeft,
+ MdKeyboardArrowRight
+} from 'react-icons/md';
+import { ConfirmStatusChange, StatusBadge, statusOptions, dataSourceTimeSheet, TimeSheet } from '.';
+import { useModal, useTimelogFilterOptions } from '@app/hooks';
+import { Checkbox } from '@components/ui/checkbox';
+import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@components/ui/accordion';
+import { clsxm } from '@/app/utils';
+import { AlertDialogConfirmation, statusColor } from '@/lib/components';
+import { Badge } from '@components/ui/badge';
import {
- Accordion,
- AccordionContent,
- AccordionItem,
- AccordionTrigger,
-} from "@components/ui/accordion"
-import { clsxm } from "@/app/utils"
-import { AlertDialogConfirmation, statusColor } from "@/lib/components"
-import { Badge } from '@components/ui/badge'
-import { EditTaskModal, RejectSelectedModal, StatusAction, StatusType, getTimesheetButtons } from "@/app/[locale]/timesheet/[memberId]/components"
-import { useTranslations } from "next-intl"
-import { formatDate } from "@/app/helpers"
-import { GroupedTimesheet, useTimesheet } from "@/app/hooks/features/useTimesheet"
-import { TaskNameInfoDisplay } from "../../task/task-displays"
-import { TimesheetStatus } from "@/app/interfaces"
+ EditTaskModal,
+ RejectSelectedModal,
+ StatusAction,
+ StatusType,
+ getTimesheetButtons
+} from '@/app/[locale]/timesheet/[memberId]/components';
+import { useTranslations } from 'next-intl';
+import { formatDate } from '@/app/helpers';
+import { GroupedTimesheet, useTimesheet } from '@/app/hooks/features/useTimesheet';
+import { TaskNameInfoDisplay } from '../../task/task-displays';
+import { TimesheetStatus } from '@/app/interfaces';
import dayjs from 'dayjs';
-
export const columns: ColumnDef
[] = [
- {
- enableHiding: false,
- id: "select",
- size: 50,
- header: ({ table }) => (
-
- table.toggleAllPageRowsSelected(!!value)}
- aria-label="Select all"
- />
- Task
-
- ),
- cell: ({ row }) => (
-
-
- row.toggleSelected(!!value)}
- aria-label="Select row"
- />
- {row.original.task}
-
- ),
- },
- {
- accessorKey: "name",
- header: ({ column }) => (
-
- ),
- cell: ({ row }) => (
-
- ),
- },
- {
- accessorKey: "employee",
- header: ({ column }) => (
-
- ),
- cell: ({ row }) => (
-
- {row.original.employee}
-
- ),
- },
- {
- accessorKey: "status",
- header: ({ column }) => (
-
-
- ),
- cell: ({ row }) => {
- return
- }
- },
- {
- accessorKey: "time",
- header: () => (
- Time
- ),
- cell: ({ row }) => (
-
- {row.original.time}
-
- ),
- },
- {
- id: "actions",
- enableHiding: false,
- cell: ({ row }) => {
-
- return (
-
- );
- },
- },
+ {
+ enableHiding: false,
+ id: 'select',
+ size: 50,
+ header: ({ table }) => (
+
+ table.toggleAllPageRowsSelected(!!value)}
+ aria-label="Select all"
+ />
+ Task
+
+ ),
+ cell: ({ row }) => (
+
+ row.toggleSelected(!!value)}
+ aria-label="Select row"
+ />
+
+ {row.original.task}
+
+
+ )
+ },
+ {
+ accessorKey: 'name',
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) =>
+ },
+ {
+ accessorKey: 'employee',
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => (
+
+ {row.original.employee}
+
+ )
+ },
+ {
+ accessorKey: 'status',
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => {
+ return ;
+ }
+ },
+ {
+ accessorKey: 'time',
+ header: () => Time
,
+ cell: ({ row }) => (
+
+ {row.original.time}
+
+ )
+ },
+ {
+ id: 'actions',
+ enableHiding: false,
+ cell: ({ row }) => {
+ return ;
+ }
+ }
];
-
-
export function DataTableTimeSheet({ data }: { data?: GroupedTimesheet[] }) {
- const {
- isOpen,
- openModal,
- closeModal
- } = useModal();
- const { deleteTaskTimesheet, loadingDeleteTimesheet, getStatusTimesheet } = useTimesheet({})
- const { handleSelectRowTimesheet, selectTimesheet, setSelectTimesheet } = useTimelogFilterOptions()
- const [isDialogOpen, setIsDialogOpen] = React.useState(false);
- const handleConfirm = () => {
- try {
- deleteTaskTimesheet()
- .then(() => {
- setSelectTimesheet([])
- setIsDialogOpen(false);
- })
- .catch((error) => {
- console.error('Delete timesheet error:', error);
- });
- } catch (error) {
- console.error('Delete timesheet error:', error);
- }
- };
- const handleCancel = () => {
- setIsDialogOpen(false);
- };
- const t = useTranslations();
- const [sorting, setSorting] = React.useState([])
- const [columnFilters, setColumnFilters] = React.useState([])
- const [columnVisibility, setColumnVisibility] = React.useState({})
- const [rowSelection, setRowSelection] = React.useState({})
- const table = useReactTable({
- data: dataSourceTimeSheet,
- columns,
- onSortingChange: setSorting,
- onColumnFiltersChange: setColumnFilters,
- getCoreRowModel: getCoreRowModel(),
- getPaginationRowModel: getPaginationRowModel(),
- getSortedRowModel: getSortedRowModel(),
- getFilteredRowModel: getFilteredRowModel(),
- onColumnVisibilityChange: setColumnVisibility,
- onRowSelectionChange: setRowSelection,
- state: {
- sorting,
- columnFilters,
- columnVisibility,
- rowSelection,
- },
- })
-
-
- const handleButtonClick = (action: StatusAction) => {
- switch (action) {
- case 'Approved':
- // TODO: Implement approval logic
- break;
- case 'Denied':
- openModal()
- break;
- case 'Deleted':
- setIsDialogOpen(true)
- break;
- default:
- console.error(`Unsupported action: ${action}`);
- }
- };
-
- return (
-
-
-
{
- // Pending implementation
- }}
- maxReasonLength={120}
- minReasonLength={0}
- closeModal={closeModal}
- isOpen={isOpen}
- />
-
- {data?.map((plan, index) => (
-
-
- {formatDate(plan.date)}
- 64:30h
-
-
-
- {Object.entries(getStatusTimesheet(plan.tasks)).map(([status, rows]) => (
-
-
-
-
-
-
-
- {status === 'DENIED' ? "REJECTED" : status}
-
- ({rows?.length})
-
-
- Total
- 24:30h
-
-
-
- {getTimesheetButtons(status as StatusType, t, true, handleButtonClick)}
-
-
-
-
- {rows?.map((task) => (
-
-
handleSelectRowTimesheet(task.id)}
- checked={selectTimesheet.includes(task.id)}
- />
-
-
-
- {task.project && task.project.name}
-
-
-
{task.employee.fullName}
-
-
-
- {task.timesheet.status}
-
-
-
-
- {dayjs(task.timesheet.createdAt).format("HH:mm:ss")}
-
-
-
- ))}
-
-
- ))}
-
-
- ))}
-
-
-
- {table.getFilteredSelectedRowModel().rows.length} of{" "}
- {table.getFilteredRowModel().rows.length} row(s) selected.
-
-
-
- Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
-
-
-
-
-
-
-
-
-
-
- )
+ const { isOpen, openModal, closeModal } = useModal();
+ const { deleteTaskTimesheet, loadingDeleteTimesheet, getStatusTimesheet } = useTimesheet({});
+ const { handleSelectRowTimesheet, selectTimesheet, setSelectTimesheet } = useTimelogFilterOptions();
+ const [isDialogOpen, setIsDialogOpen] = React.useState(false);
+ const handleConfirm = () => {
+ try {
+ deleteTaskTimesheet()
+ .then(() => {
+ setSelectTimesheet([]);
+ setIsDialogOpen(false);
+ })
+ .catch((error) => {
+ console.error('Delete timesheet error:', error);
+ });
+ } catch (error) {
+ console.error('Delete timesheet error:', error);
+ }
+ };
+ const handleCancel = () => {
+ setIsDialogOpen(false);
+ };
+ const t = useTranslations();
+ const [sorting, setSorting] = React.useState([]);
+ const [columnFilters, setColumnFilters] = React.useState([]);
+ const [columnVisibility, setColumnVisibility] = React.useState({});
+ const [rowSelection, setRowSelection] = React.useState({});
+ const table = useReactTable({
+ data: dataSourceTimeSheet,
+ columns,
+ onSortingChange: setSorting,
+ onColumnFiltersChange: setColumnFilters,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ getSortedRowModel: getSortedRowModel(),
+ getFilteredRowModel: getFilteredRowModel(),
+ onColumnVisibilityChange: setColumnVisibility,
+ onRowSelectionChange: setRowSelection,
+ state: {
+ sorting,
+ columnFilters,
+ columnVisibility,
+ rowSelection
+ }
+ });
+
+ const handleButtonClick = (action: StatusAction) => {
+ switch (action) {
+ case 'Approved':
+ // TODO: Implement approval logic
+ break;
+ case 'Denied':
+ openModal();
+ break;
+ case 'Deleted':
+ setIsDialogOpen(true);
+ break;
+ default:
+ console.error(`Unsupported action: ${action}`);
+ }
+ };
+
+ return (
+
+
+
{
+ // Pending implementation
+ }}
+ maxReasonLength={120}
+ minReasonLength={0}
+ closeModal={closeModal}
+ isOpen={isOpen}
+ />
+
+ {data?.map((plan, index) => (
+
+
+ {formatDate(plan.date)}
+ 64:30h
+
+
+
+ {Object.entries(getStatusTimesheet(plan.tasks)).map(([status, rows]) => (
+
+
+
+
+
+
+
+ {status === 'DENIED' ? 'REJECTED' : status}
+
+ ({rows?.length})
+
+
+ Total
+ 24:30h
+
+
+
+ {getTimesheetButtons(status as StatusType, t, true, handleButtonClick)}
+
+
+
+
+ {rows?.map((task) => (
+
+
handleSelectRowTimesheet(task.id)}
+ checked={selectTimesheet.includes(task.id)}
+ />
+
+
+
+ {task.project && task.project.name}
+
+
+
{task.employee.fullName}
+
+
+
+ {task.timesheet.status}
+
+
+
+ {dayjs(task.timesheet.createdAt).format('HH:mm:ss')}
+
+
+
+ ))}
+
+
+ ))}
+
+
+ ))}
+
+
+
+ {table.getFilteredSelectedRowModel().rows.length} of {table.getFilteredRowModel().rows.length}{' '}
+ row(s) selected.
+
+
+
+ Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
+
+
+
+
+
+
+
+
+ );
}
-
-
-
export function SelectFilter({ selectedStatus }: { selectedStatus?: string }) {
-
- const { isOpen, closeModal, openModal } = useModal();
- const [selected] = React.useState(selectedStatus);
- const [newStatus, setNewStatus] = React.useState('');
-
- const getColorClass = () => {
- switch (selected) {
- case "Rejected":
- return "text-red-500 border-gray-200";
- case "Approved":
- return "text-green-500 border-gray-200";
- case "Pending":
- return "text-orange-500 border-gray-200";
- default:
- return "text-gray-500 border-gray-200";
- }
- };
-
-
- const onValueChanges = (value: string) => {
- setNewStatus(value);
- openModal()
- }
-
- return (
- <>
-
-
-
-
- >
- );
+ const { isOpen, closeModal, openModal } = useModal();
+ const [selected] = React.useState(selectedStatus);
+ const [newStatus, setNewStatus] = React.useState('');
+
+ const getColorClass = () => {
+ switch (selected) {
+ case 'Rejected':
+ return 'text-red-500 border-gray-200';
+ case 'Approved':
+ return 'text-green-500 border-gray-200';
+ case 'Pending':
+ return 'text-orange-500 border-gray-200';
+ default:
+ return 'text-gray-500 border-gray-200';
+ }
+ };
+
+ const onValueChanges = (value: string) => {
+ setNewStatus(value);
+ openModal();
+ };
+
+ return (
+ <>
+
+
+
+ >
+ );
}
const TaskActionMenu = ({ idTasks }: { idTasks: string | number }) => {
- const {
- isOpen: isEditTask,
- openModal: isOpenModalEditTask,
- closeModal: isCloseModalEditTask
- } = useModal();
- return (
- <>
- {
-
- }
-
-
-
-
-
-
- Edit
-
-
-
- Delete
-
-
-
- >
-
- );
+ const { isOpen: isEditTask, openModal: isOpenModalEditTask, closeModal: isCloseModalEditTask } = useModal();
+ return (
+ <>
+ {}
+
+
+
+
+
+
+ Edit
+
+
+
+
+ Delete
+
+
+
+ >
+ );
};
const TaskDetails = ({ description, name }: { description: string; name: string }) => {
- return (
-
-
- ever
-
-
- {name}
-
-
{description}
-
- );
+ return (
+
+
+ ever
+
+
+ {name}
+
+
{description}
+
+ );
};
export const StatusTask = () => {
- const t = useTranslations();
- return (
- <>
-
-
- Change status
-
-
-
- {statusOptions?.map((status, index) => (
-
-
-
- ))}
-
-
-
-
-
- Billable
-
-
-
-
-
- {t('pages.timesheet.BILLABLE.YES')}
-
-
-
-
- {t('pages.timesheet.BILLABLE.NO')}
-
-
-
-
-
- >
- )
-}
-
+ const t = useTranslations();
+ return (
+ <>
+
+
+ Change status
+
+
+
+ {statusOptions?.map((status, index) => (
+
+
+
+ ))}
+
+
+
+
+
+ Billable
+
+
+
+
+
+ {t('pages.timesheet.BILLABLE.YES')}
+
+
+
+
+ {t('pages.timesheet.BILLABLE.NO')}
+
+
+
+
+
+ >
+ );
+};
const getBadgeColor = (timesheetStatus: TimesheetStatus | null) => {
- switch (timesheetStatus) {
- case 'DRAFT':
- return 'bg-gray-300';
- case 'PENDING':
- return 'bg-yellow-400';
- case 'IN REVIEW':
- return 'bg-blue-500';
- case 'DENIED':
- return 'bg-red-500';
- case 'APPROVED':
- return 'bg-green-500';
- default:
- return 'bg-gray-100';
- }
+ switch (timesheetStatus) {
+ case 'DRAFT':
+ return 'bg-gray-300';
+ case 'PENDING':
+ return 'bg-yellow-400';
+ case 'IN REVIEW':
+ return 'bg-blue-500';
+ case 'DENIED':
+ return 'bg-red-500';
+ case 'APPROVED':
+ return 'bg-green-500';
+ default:
+ return 'bg-gray-100';
+ }
};