Skip to content

Commit

Permalink
recent projects
Browse files Browse the repository at this point in the history
version-patch
  • Loading branch information
trueberryless committed Jul 7, 2024
1 parent 3d7c9ac commit a969a18
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 220 deletions.
2 changes: 1 addition & 1 deletion src/components/dashboard/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ import { useUser } from "../UserContext";
import { loadData } from "@/utils/load";
import { useEffect } from "react";
import { Task, User } from "@/models";
import { getMostRecentTimeSpanDate } from "@/models/task";
import { getMostRecentTimeSpanDate } from "@/utils/taskUtils";
import { CalendarDateRangePicker } from "./date-range-picker";
import { Overview } from "./overview";
import { RecentSales } from "./recent-sales";
Expand Down
123 changes: 71 additions & 52 deletions src/components/projects/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,29 @@ import {

import { DataTablePagination } from "./data-table-pagination";
import { DataTableToolbar } from "./data-table-toolbar";
import { Card, CardContent, CardHeader } from "../ui/card";
import { DataTableViewOptions } from "./data-table-view-options";

interface TEntity {
id: number;
}

interface DataTableProps<TData extends TEntity, TValue> {
title: string;
columns: ColumnDef<TData, TValue>[];
data: TData[];
pagination?: boolean;
clickableRows?: boolean;
filtering?: boolean;
}

export function DataTable<TData extends TEntity, TValue>({
title,
columns,
data,
pagination,
clickableRows,
filtering,
}: DataTableProps<TData, TValue>) {
const router = useRouter();

Expand Down Expand Up @@ -83,58 +89,71 @@ export function DataTable<TData extends TEntity, TValue>({
}

return (
<div className="space-y-4">
<DataTableToolbar table={table} />
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
onClick={() => handleRowClick(row.original.id)}
className={clickableRows ? "cursor-pointer" : ""}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id} className="truncate">
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
<Card>
<CardHeader>
<div className="flex items-center justify-between">
{title}
{!filtering && <DataTableViewOptions table={table} />}
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
{filtering && <DataTableToolbar table={table} />}
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
onClick={() => handleRowClick(row.original.id)}
className={clickableRows ? "cursor-pointer" : ""}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id} className="truncate">
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
{pagination && <DataTablePagination table={table} />}
</div>
</TableRow>
)}
</TableBody>
</Table>
</div>
{pagination && <DataTablePagination table={table} />}
</div>
</CardContent>
</Card>
);
}
2 changes: 1 addition & 1 deletion src/components/tasks/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { priorities, statuses } from "@/models/task";
import { Badge } from "../ui/badge";
import { format } from "date-fns";
import { DataTableRowActions } from "../tasks/data-table-row-actions";
import { calculateTotalTime, msToTime } from "@/models/task";
import { calculateTotalTime, msToTime } from "@/utils/taskUtils";
import { useEffect } from "react";
import { loadData } from "@/utils/load";

Expand Down
51 changes: 0 additions & 51 deletions src/models/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,54 +72,3 @@ export const priorities = [
icon: ArrowUp,
},
];

export const getMostRecentTimeSpanDate = (task: Task) => {
const dates = task.timeSpans.map((span) => new Date(span.end ?? span.start).getTime());
return new Date(Math.max(...dates));
};

export const getProjectValue = (task: Task): string => {
const user = loadData();
const projects = user?.projects || [];
const project = projects.find((project) => project.tasks.some((t: Task) => t.id === task.id));
return project ? project.name : "Unknown";
};

export const getProject = (task: Task): Project | undefined => {
const user = loadData();
const projects = user?.projects || [];
return projects.find((project) => project.tasks.some((t: Task) => t.id === task.id));
};

export const calculateTotalTime = (task: Task): number => {
return task.timeSpans.reduce((total, timeSpan) => {
if (timeSpan.end !== null) {
const start = Date.parse(String(timeSpan.start));
const end = Date.parse(String(timeSpan.end));
return total + (end - start);
}
return total;
}, 0);
};

export const msToTime = (duration: number) => {
let seconds = Math.floor((duration / 1000) % 60),
minutes = Math.floor((duration / (1000 * 60)) % 60),
hours = Math.floor((duration / (1000 * 60 * 60)) % 24);

// Initialize an array to store non-zero time components
let timeComponents: string[] = [];

if (hours > 0) {
timeComponents.push(`${hours} hour${hours > 1 ? "s" : ""}`);
}
if (minutes > 0) {
timeComponents.push(`${minutes} minute${minutes > 1 ? "s" : ""}`);
}
if (seconds > 0 || timeComponents.length === 0) {
timeComponents.push(`${seconds} second${seconds > 1 ? "s" : ""}`);
}

// Join time components with commas and return as a single string
return timeComponents.join(", ");
};
Loading

0 comments on commit a969a18

Please sign in to comment.