{["Today", "Last 7 days", "Last 30 days", `This year (${new Date().getFullYear()})`, "Custom Date Range"].map((label, index) => (
@@ -185,7 +208,9 @@ export function DatePickerFilter({
}
}}
modifiersClassNames={{
- disabled: 'text-gray-300 cursor-not-allowed',
+ disabled: 'text-[#6989AA] cursor-not-allowed',
+ selected: '!rounded-full bg-primary text-white',
+ today: '!rounded-full bg-[#BCCAD9] text-white'
}}
disabled={[
...(minDate ? [{ before: minDate }] : []),
diff --git a/apps/web/app/[locale]/timesheet/components/TimesheetView.tsx b/apps/web/app/[locale]/timesheet/[memberId]/components/TimesheetView.tsx
similarity index 51%
rename from apps/web/app/[locale]/timesheet/components/TimesheetView.tsx
rename to apps/web/app/[locale]/timesheet/[memberId]/components/TimesheetView.tsx
index 3d29bb856..d46a877b1 100644
--- a/apps/web/app/[locale]/timesheet/components/TimesheetView.tsx
+++ b/apps/web/app/[locale]/timesheet/[memberId]/components/TimesheetView.tsx
@@ -1,9 +1,10 @@
+import { IDailyPlan } from '@/app/interfaces'
import { DataTableTimeSheet } from 'lib/features/integrations/calendar'
-export function TimesheetView() {
+export function TimesheetView({ data }: { data?: IDailyPlan[] }) {
return (
-
+
)
}
diff --git a/apps/web/app/[locale]/timesheet/components/index.tsx b/apps/web/app/[locale]/timesheet/[memberId]/components/index.tsx
similarity index 76%
rename from apps/web/app/[locale]/timesheet/components/index.tsx
rename to apps/web/app/[locale]/timesheet/[memberId]/components/index.tsx
index ed9e14172..a5c0da311 100644
--- a/apps/web/app/[locale]/timesheet/components/index.tsx
+++ b/apps/web/app/[locale]/timesheet/[memberId]/components/index.tsx
@@ -5,3 +5,5 @@ export * from './TimesheetFilter';
export * from './FrequencySelect';
export * from './FilterWithStatus';
export * from './TimesheetFilterDate';
+export * from './TimeSheetFilterPopover'
+export * from './TimesheetAction'
diff --git a/apps/web/app/[locale]/timesheet/page.tsx b/apps/web/app/[locale]/timesheet/[memberId]/page.tsx
similarity index 89%
rename from apps/web/app/[locale]/timesheet/page.tsx
rename to apps/web/app/[locale]/timesheet/[memberId]/page.tsx
index 985677e29..3e57d8e00 100644
--- a/apps/web/app/[locale]/timesheet/page.tsx
+++ b/apps/web/app/[locale]/timesheet/[memberId]/page.tsx
@@ -5,7 +5,7 @@ import { useTranslations } from 'next-intl';
import { withAuthentication } from 'lib/app/authenticator';
import { Breadcrumb, Container, Divider } from 'lib/components';
import { Footer, MainLayout } from 'lib/layout';
-import { useLocalStorageState, useOrganizationTeams } from '@app/hooks';
+import { useAuthenticateUser, useDailyPlan, useLocalStorageState, useOrganizationTeams } from '@app/hooks';
import { clsxm } from '@app/utils';
import { fullWidthState } from '@app/stores/fullWidth';
import { useAtomValue } from 'jotai';
@@ -14,6 +14,7 @@ import { CalendarView, TimesheetCard, TimesheetFilter, TimesheetView } from './c
import { CalendarDaysIcon, Clock, User2 } from 'lucide-react';
import { GrTask } from "react-icons/gr";
import { GoSearch } from "react-icons/go";
+import { getGreeting } from '@/app/helpers';
type TimesheetViewMode = "ListView" | "CalendarView";
@@ -28,21 +29,26 @@ interface FooterTimeSheetProps {
fullWidth: boolean;
}
-function TimeSheetPage() {
+const TimeSheet = React.memo(function TimeSheetPage({ params }: { params: { memberId: string } }) {
const t = useTranslations();
+ const { user } = useAuthenticateUser();
+
+ const { sortedPlans } = useDailyPlan();
+
+ const username = user?.name || user?.firstName || user?.lastName || user?.username;
const [timesheetNavigator, setTimesheetNavigator] = useLocalStorageState
('timesheet-viewMode', 'ListView');
const fullWidth = useAtomValue(fullWidthState);
const { isTrackingEnabled, activeTeam } = useOrganizationTeams();
- const params = useParams<{ locale: string }>();
- const currentLocale = params ? params.locale : null;
+ const paramsUrl = useParams<{ locale: string }>();
+ const currentLocale = paramsUrl ? paramsUrl.locale : null;
const breadcrumbPath = useMemo(
() => [
{ title: JSON.parse(t('pages.home.BREADCRUMB')), href: '/' },
{ title: activeTeam?.name || '', href: '/' },
- { title: 'Timesheet', href: `/${currentLocale}/timesheet` }
+ { title: 'Timesheet', href: `/${currentLocale}/timesheet/${params.memberId}` }
],
[activeTeam?.name, currentLocale, t]
);
@@ -66,7 +72,7 @@ function TimeSheetPage() {
-
Good morning, Ruslan !
+ {getGreeting()}, {username} !
This is your personal timesheet dashboard, showing you what needs your attention now.
@@ -113,6 +119,9 @@ function TimeSheetPage() {
@@ -122,7 +131,7 @@ function TimeSheetPage() {
{timesheetNavigator === 'ListView' ?
-
+
:
}
@@ -133,9 +142,9 @@ function TimeSheetPage() {
>
)
-}
+})
-export default withAuthentication(TimeSheetPage, { displayName: 'TimeSheet' });
+export default withAuthentication(TimeSheet, { displayName: 'TimeSheet' });
const FooterTimeSheet: React.FC
= ({ fullWidth }) => {
return (
diff --git a/apps/web/app/helpers/date.ts b/apps/web/app/helpers/date.ts
index 5bc4349fa..c038dceeb 100644
--- a/apps/web/app/helpers/date.ts
+++ b/apps/web/app/helpers/date.ts
@@ -198,3 +198,20 @@ export function formatTimeString(timeString: string): string {
return result.length ? result : '0h 00m';
}
+
+export const getGreeting = () => {
+ const GREETING_TIMES = {
+ MORNING_START: 5,
+ AFTERNOON_START: 12,
+ EVENING_START: 18
+ } as const
+ const currentHour = new Date().getHours();
+
+ if (currentHour >= GREETING_TIMES.MORNING_START && currentHour < GREETING_TIMES.AFTERNOON_START) {
+ return "Good morning";
+ } else if (currentHour >= GREETING_TIMES.AFTERNOON_START && currentHour < GREETING_TIMES.EVENING_START) {
+ return "Good afternoon";
+ } else {
+ return "Good evening";
+ }
+}
diff --git a/apps/web/components/app-sidebar.tsx b/apps/web/components/app-sidebar.tsx
index 8465d56c1..44536f9a5 100644
--- a/apps/web/components/app-sidebar.tsx
+++ b/apps/web/components/app-sidebar.tsx
@@ -69,60 +69,60 @@ export function AppSidebar({ publicTeam, ...props }: AppSidebarProps) {
items:
favoriteTasks && favoriteTasks.length > 0
? favoriteTasks
- .sort((a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase()))
- .map((task, index) => ({
- title: task?.title,
- url: '#',
- component: (
-
-
-
- {task && (
- // Show task issue and task number
-
- )}
-
-
- #{task?.taskNumber}
-
-
- {task?.title}
-
+ .sort((a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase()))
+ .map((task, index) => ({
+ title: task?.title,
+ url: '#',
+ component: (
+
+
+
+ {task && (
+ // Show task issue and task number
+
+ )}
+
+
+ #{task?.taskNumber}
+
+
+ {task?.title}
-
- toggleFavorite(task)}
- />
-
-
- )
- }))
+
+
+ toggleFavorite(task)}
+ />
+
+
+ )
+ }))
: [
- {
- title: t('common.NO_FAVORITE_TASK'),
- url: '#',
- label: 'no-task'
- }
- ]
+ {
+ title: t('common.NO_FAVORITE_TASK'),
+ url: '#',
+ label: 'no-task'
+ }
+ ]
},
{
title: t('sidebar.TASKS'),
@@ -142,73 +142,73 @@ export function AppSidebar({ publicTeam, ...props }: AppSidebarProps) {
},
...(userManagedTeams && userManagedTeams.length > 0
? [
- {
- title: t('sidebar.PROJECTS'),
- label: 'projects',
- url: '#',
- icon: FolderKanban,
- items: [
- ...userManagedTeams
- .sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()))
- .map((team, index) => ({
- title: team.name,
- url: '#',
- component: (
-
-
-
- )
- })),
- {
- title: t('common.NO_PROJECT'),
+ {
+ title: t('sidebar.PROJECTS'),
+ label: 'projects',
+ url: '#',
+ icon: FolderKanban,
+ items: [
+ ...userManagedTeams
+ .sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()))
+ .map((team, index) => ({
+ title: team.name,
url: '#',
component: (
-
-
)
- }
- ]
- }
- ]
+ })),
+ {
+ title: t('common.NO_PROJECT'),
+ url: '#',
+ component: (
+
+
+
+ {t('common.CREATE_PROJECT')}
+
+
+ )
+ }
+ ]
+ }
+ ]
: []),
{
title: t('sidebar.MY_WORKS'),
@@ -227,42 +227,42 @@ export function AppSidebar({ publicTeam, ...props }: AppSidebarProps) {
},
...(isTeamManager
? [
- {
- title: t('sidebar.REPORTS'),
- url: '#',
- icon: SquareActivity,
- items: [
- {
- title: t('sidebar.TIMESHEETS'),
- url: '#'
- },
- {
- title: t('sidebar.MANUAL_TIME_EDIT'),
- url: '#'
- },
- {
- title: t('sidebar.WEEKLY_LIMIT'),
- url: '#'
- },
- {
- title: t('sidebar.ACTUAL_AND_EXPECTED_HOURS'),
- url: '#'
- },
- {
- title: t('sidebar.PAYMENTS_DUE'),
- url: '#'
- },
- {
- title: t('sidebar.PROJECT_BUDGET'),
- url: '#'
- },
- {
- title: t('sidebar.TIME_AND_ACTIVITY'),
- url: '#'
- }
- ]
- }
- ]
+ {
+ title: t('sidebar.REPORTS'),
+ url: '#',
+ icon: SquareActivity,
+ items: [
+ {
+ title: t('sidebar.TIMESHEETS'),
+ url: `/timesheet/${user?.id}?name=${username || ''}`
+ },
+ {
+ title: t('sidebar.MANUAL_TIME_EDIT'),
+ url: '#'
+ },
+ {
+ title: t('sidebar.WEEKLY_LIMIT'),
+ url: '#'
+ },
+ {
+ title: t('sidebar.ACTUAL_AND_EXPECTED_HOURS'),
+ url: '#'
+ },
+ {
+ title: t('sidebar.PAYMENTS_DUE'),
+ url: '#'
+ },
+ {
+ title: t('sidebar.PROJECT_BUDGET'),
+ url: '#'
+ },
+ {
+ title: t('sidebar.TIME_AND_ACTIVITY'),
+ url: '#'
+ }
+ ]
+ }
+ ]
: [])
]
};
diff --git a/apps/web/components/ui/data-table.tsx b/apps/web/components/ui/data-table.tsx
index 8a9ceaf8e..09c74e340 100644
--- a/apps/web/components/ui/data-table.tsx
+++ b/apps/web/components/ui/data-table.tsx
@@ -86,9 +86,9 @@ function DataTable({ columns, data, footerRows, isHeader }: DataT
{header.isPlaceholder
? null
: flexRender(
- header.column.columnDef.header,
- header.getContext()
- )}
+ header.column.columnDef.header,
+ header.getContext()
+ )}
diff --git a/apps/web/lib/components/custom-select/multi-select.tsx b/apps/web/lib/components/custom-select/multi-select.tsx
index a88cb2e65..3b8a298b4 100644
--- a/apps/web/lib/components/custom-select/multi-select.tsx
+++ b/apps/web/lib/components/custom-select/multi-select.tsx
@@ -1,8 +1,10 @@
+import { clsxm } from '@/app/utils';
import { Button } from '@components/ui/button';
import { Popover, PopoverContent, PopoverTrigger } from '@components/ui/popover';
import { cn } from 'lib/utils';
import { useEffect, useState, useRef } from 'react';
import { MdOutlineKeyboardArrowDown, MdClose } from 'react-icons/md';
+import { statusColor } from '..';
interface MultiSelectProps {
items: T[];
@@ -134,7 +136,11 @@ export function MultiSelect({
{selectedItems.map((item) => (
{itemToString(item)}
= {
+ Pending: {
+ bg: 'bg-[#FBB650]',
+ text: 'text-[#FBB650]',
+ bgOpacity: 'rgba(251, 182, 80, 0.1)'
+ },
+ Approved: {
+ bg: 'bg-[#30B366]',
+ text: 'text-[#30B366]',
+ bgOpacity: 'rgba(48, 179, 102, 0.1)'
+ },
+ Rejected: {
+ bg: 'bg-[#dc2626]',
+ text: 'text-[#dc2626]',
+ bgOpacity: 'rgba(220, 38, 38, 0.1)'
+ }
+};
+
+
+/**
+* Returns color scheme for a given status
+* @param status - The status string to get colors for
+* @returns StatusColorScheme object or empty object if status not found
+*/
+export const statusColor = (status: string): Partial => {
+ return STATUS_COLORS[status] || {};
+};
diff --git a/apps/web/lib/features/integrations/calendar/confirm-change-status.tsx b/apps/web/lib/features/integrations/calendar/confirm-change-status.tsx
index 9d1663b4a..22155b14c 100644
--- a/apps/web/lib/features/integrations/calendar/confirm-change-status.tsx
+++ b/apps/web/lib/features/integrations/calendar/confirm-change-status.tsx
@@ -1,8 +1,8 @@
import { clsxm } from '@app/utils';
import { Badge } from '@components/ui/badge';
import { Button } from '@components/ui/button';
-import { Modal } from 'lib/components'
-import React from 'react'
+import { Modal } from 'lib/components';
+import React from 'react';
interface ConfirmStatusChangeProps {
isOpen?: boolean;
@@ -93,11 +93,11 @@ export function StatusBadge({ selectedStatus, filterNumber }: { selectedStatus?:
const getColorClass = () => {
switch (selected) {
case "Rejected":
- return `text-black ${filterNumber ? "border-gray-200 dark:border-gray-700" : "!bg-red-500"} `;
+ return `text-black ${filterNumber ? "border-gray-200 dark:border-gray-700" : "!bg-[#dc2626]"} `;
case "Approved":
- return `text-black ${filterNumber ? "border-gray-200 dark:border-gray-700" : "!bg-green-500"}`;
+ return `text-black ${filterNumber ? "border-gray-200 dark:border-gray-700" : "!bg-[#30B366]"}`;
case "Pending":
- return `text-black ${filterNumber ? "border-gray-200 dark:border-gray-700" : "!bg-orange-500"} `;
+ return `text-black ${filterNumber ? "border-gray-200 dark:border-gray-700" : "!bg-[#FBB650]"} `;
default:
return `text-gray-500 dark:text-gray-200 border-gray-200 dark:border-gray-700 !py-0 font-normal`;
}
diff --git a/apps/web/lib/features/integrations/calendar/helper-calendar.ts b/apps/web/lib/features/integrations/calendar/helper-calendar.ts
index 697efb5e1..577324061 100644
--- a/apps/web/lib/features/integrations/calendar/helper-calendar.ts
+++ b/apps/web/lib/features/integrations/calendar/helper-calendar.ts
@@ -1,3 +1,4 @@
+
export type timesheetCalendar = 'TimeSheet' | 'Calendar';
export const statusOptions = [
@@ -16,11 +17,146 @@ export type TimeSheet = {
time: string
}
+export type headTimeSheet = {
+
+ deletedAt: string,
+ id: string,
+ createdAt: Date | string,
+ updatedAt: Date | string,
+ isActive: boolean,
+ isArchived: boolean,
+ archivedAt: string,
+ tenantId: string,
+ organizationId: string,
+ number: number | string,
+ prefix: string,
+ title: string,
+ description: string,
+ status: string,
+ priority: string,
+ size: string,
+ issueType: string,
+ estimate: number,
+ dueDate: string,
+ public: boolean,
+ startDate: string,
+ resolvedAt: string,
+ version: string,
+ isDraft: false,
+ parentId: string,
+ projectId: string,
+ creatorId: string,
+ organizationSprintId: string,
+ taskStatusId: string,
+ taskSizeId: string,
+ taskPriorityId: string,
+ members:
+ {
+ deletedAt: string,
+ id: string,
+ createdAt: Date | string,
+ updatedAt: Date | string,
+ isActive: true,
+ isArchived: false,
+ archivedAt: string,
+ tenantId: string,
+ organizationId: string,
+ valueDate: string,
+ short_description: string,
+ description: string,
+ startedWorkOn: string,
+ endWork: string,
+ payPeriod: string,
+ billRateValue: 0,
+ minimumBillingRate: 0,
+ billRateCurrency: string,
+ reWeeklyLimit: 0,
+ offerDate: string,
+ acceptDate: string,
+ rejectDate: string,
+ employeeLevel: string,
+ anonymousBonus: string,
+ averageIncome: string,
+ averageBonus: string,
+ totalWorkHours: string,
+ averageExpenses: string,
+ show_anonymous_bonus: string,
+ show_average_bonus: string,
+ show_average_expenses: string,
+ show_average_income: string,
+ show_billrate: string,
+ show_payperiod: string,
+ show_start_work_on: string,
+ isJobSearchActive: string,
+ linkedInUrl: string,
+ facebookUrl: string,
+ instagramUrl: string,
+ twitterUrl: string,
+ githubUrl: string,
+ gitlabUrl: string,
+ upworkUrl: string,
+ stackoverflowUrl: string,
+ isVerified: string,
+ isVetted: string,
+ totalJobs: string,
+ jobSuccess: string,
+ profile_link: string,
+ isTrackingEnabled: false,
+ isOnline: false,
+ isAway: false,
+ isTrackingTime: false,
+ allowScreenshotCapture: true,
+ allowManualTime: false,
+ allowModifyTime: false,
+ allowDeleteTime: false,
+ upworkId: string,
+ linkedInId: string,
+ userId: string,
+ contactId: string,
+ organizationPositionId: string,
+ user: {
+ deletedAt: string,
+ id: string,
+ createdAt: Date | string,
+ updatedAt: Date | string,
+ isActive: boolean,
+ isArchived: boolean,
+ archivedAt: string,
+ tenantId: string,
+ thirdPartyId: string,
+ firstName: string,
+ lastName: string,
+ email: string,
+ phoneNumber: string,
+ username: string,
+ timeZone: number,
+ imageUrl: string,
+ preferredLanguage: string,
+ preferredComponentLayout: string,
+ lastLoginAt: string,
+ roleId: string,
+ imageId: string,
+ defaultTeamId: string,
+ lastTeamId: string,
+ defaultOrganizationId: string,
+ lastOrganizationId: string,
+ image: string,
+ name: string,
+ isEmailVerified: true
+ },
+ fullName: string,
+ isDeleted: false,
+ }
+
+ taskNumber: string
+
+}
+
export const dataSourceTimeSheet: TimeSheet[] = [
{
id: 1,
- task: "chore(deps-dev): bump karma from 5.2.3 to 6.3.16chore",
- name: "Gauzy Platform SaaS",
+ task: "#324 Working on UI Design & making prototype for user testing tomorrow & making prototype for user testing tomorrow",
+ name: "Ever Gauzy",
description: "Members count 11",
employee: "Ruslan Konviser",
status: "Approved",
@@ -28,7 +164,7 @@ export const dataSourceTimeSheet: TimeSheet[] = [
},
{
id: 2,
- task: "chore(deps-dev): bump karma from 5.2.3 to 6.3.16chore",
+ task: "#321 Spike for creating calendar views on mobile",
name: "Gauzy Platform SaaS",
description: "Members count 11",
employee: "Ruslan Konviser",
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 15b17e743..9ab1df2a2 100644
--- a/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx
+++ b/apps/web/lib/features/integrations/calendar/table-time-sheet.tsx
@@ -13,7 +13,7 @@ import {
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table"
-import { ArrowUpDownIcon, MoreHorizontal, } from "lucide-react"
+import { ArrowUpDownIcon, MoreHorizontal } from "lucide-react"
import { Button } from "@components/ui/button"
import {
DropdownMenu,
@@ -29,10 +29,7 @@ import {
import {
Table,
TableBody,
- TableCell,
- TableHead,
- TableHeader,
- TableRow,
+ TableCell, TableRow
} from "@components/ui/table"
import {
Select,
@@ -49,31 +46,24 @@ import {
MdKeyboardArrowLeft,
MdKeyboardArrowRight
} from "react-icons/md"
-import { ConfirmStatusChange, StatusBadge, TimeSheet, dataSourceTimeSheet, statusOptions } from "."
+import { ConfirmStatusChange, StatusBadge, statusOptions, dataSourceTimeSheet, TimeSheet } from "."
import { useModal } from "@app/hooks"
import { Checkbox } from "@components/ui/checkbox"
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@components/ui/accordion"
+import { clsxm } from "@/app/utils"
+import { statusColor } from "@/lib/components"
+import { Badge } from '@components/ui/badge'
+import { IDailyPlan } from "@/app/interfaces"
+import { StatusType, getTimesheetButtons } from "@/app/[locale]/timesheet/[memberId]/components"
-
-
-
-
-function getStatusColor(status: string) {
- switch (status) {
- case 'Rejected':
- return "text-red-400";
- case 'Approved':
- return "text-gray-500";
- case 'Pending':
- return "text-orange-400";
- default:
- return "";
- }
-}
-
-
export const columns: ColumnDef[] = [
{
enableHiding: false,
@@ -94,13 +84,13 @@ export const columns: ColumnDef[] = [
),
cell: ({ row }) => (
-
+
row.toggleSelected(!!value)}
aria-label="Select row"
/>
- {row.original.task}
+ {row.original.id}
),
},
@@ -164,7 +154,7 @@ export const columns: ColumnDef
[] = [
Time
),
cell: ({ row }) => (
-
+
{row.original.time}
),
@@ -183,12 +173,11 @@ export const columns: ColumnDef
[] = [
-export function DataTableTimeSheet() {
+export function DataTableTimeSheet({ data }: { data?: IDailyPlan[] }) {
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,
@@ -208,109 +197,121 @@ export function DataTableTimeSheet() {
},
})
- return (
- <>
+ const groupedRows = {
+ Pending: table.getRowModel().rows.filter(row => row.original.status === "Pending"),
+ Approved: table.getRowModel().rows.filter(row => row.original.status === "Approved"),
+ Rejected: table.getRowModel().rows.filter(row => row.original.status === "Rejected")
+ };
-
-
-
-
- {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.
-
-
- )}
-
-
+ return (
+
+
+
+ {/*
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => (
+
+ {header.isPlaceholder ? null : flexRender(header.column.````columnDef.header, header.getContext())}
+
+ ))}
+
+ ))}
+ */}
+
+
+ {Object.entries(groupedRows).map(([status, rows]) => (
+
+
+
+
+
+
+
+ {status}
+
+ ({rows.length})
+
+
+ Total
+ 24:30h
+
+
+
+ {getTimesheetButtons(status as StatusType)}
+
+
+
+
+ {rows.length ? (
+ rows.map((row) => (
+
+ {row.getVisibleCells().map((cell) => (
+
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+
+ ))}
+
+ ))
+ ) : (
+
+ No results.
+
+ )}
+
+
+ ))}
+
+
+
+
+
+
+ {table.getFilteredSelectedRowModel().rows.length} of{" "}
+ {table.getFilteredRowModel().rows.length} row(s) selected.
-
-
- {table.getFilteredSelectedRowModel().rows.length} of{" "}
- {table.getFilteredRowModel().rows.length} row(s) selected.
-
-
- Page 1 of 10
- table.previousPage()}
- disabled={!table.getCanPreviousPage()}
- >
-
-
- table.previousPage()}
- disabled={!table.getCanPreviousPage()}
- >
-
-
- table.previousPage()}
- disabled={!table.getCanPreviousPage()}
- >
-
-
- table.nextPage()}
- disabled={!table.getCanNextPage()}
- >
-
-
-
+
+
+ Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
+
+ table.setPageIndex(0)}
+ disabled={!table.getCanPreviousPage()}>
+
+
+ table.previousPage()}
+ disabled={!table.getCanPreviousPage()}>
+
+
+ table.nextPage()}
+ disabled={!table.getCanNextPage()}>
+
+
+ table.setPageIndex(table.getPageCount() - 1)}
+ disabled={!table.getCanNextPage()}>
+
+
- >
+
+
)
}
@@ -334,8 +335,6 @@ export function SelectFilter({ selectedStatus }: { selectedStatus?: string }) {
default:
return "text-gray-500 border-gray-200";
}
-
-
};
@@ -409,11 +408,11 @@ const TaskActionMenu = ({ idTasks }: { idTasks: any }) => {
const TaskDetails = ({ description, name }: { description: string; name: string }) => {
return (
-
-
-
ever
+
+
+ ever
-
+
{name}
{description}
@@ -423,22 +422,43 @@ const TaskDetails = ({ description, name }: { description: string; name: string
export const StatusTask = () => {
return (
-
-
- Status
-
-
-
- {statusOptions?.map((status, index) => (
-
+ <>
+
+
+ Change status
+
+
+
+ {statusOptions?.map((status, index) => (
+
+
+
+ ))}
+
+
+
+
+
+ Billable
+
+
+
+
- ))}
-
-
-
+
+
+ No
+
+
+
+
+
+ >
)
}
diff --git a/apps/web/lib/features/integrations/calendar/time-sheet-filter-popover.tsx b/apps/web/lib/features/integrations/calendar/time-sheet-filter-popover.tsx
index d441894e2..40a1eb39f 100644
--- a/apps/web/lib/features/integrations/calendar/time-sheet-filter-popover.tsx
+++ b/apps/web/lib/features/integrations/calendar/time-sheet-filter-popover.tsx
@@ -1,5 +1,5 @@
import { useOrganizationTeams, useTeamTasks } from "@app/hooks";
-import { Button } from "@components/ui/button"
+import { Button } from "@components/ui/button";
import { Modal } from "lib/components";
import { statusOptions } from "@app/constants";
import { MultiSelect } from "lib/components/custom-select/multi-select";
diff --git a/apps/web/lib/features/user-profile-plans.tsx b/apps/web/lib/features/user-profile-plans.tsx
index 0ec07b9c9..203d5808e 100644
--- a/apps/web/lib/features/user-profile-plans.tsx
+++ b/apps/web/lib/features/user-profile-plans.tsx
@@ -444,9 +444,8 @@ export function PlanHeader({ plan, planMode }: { plan: IDailyPlan; planMode: Fil
return (
{/* Planned Time */}