feat: update ProjectE application

This commit is contained in:
2026-07-18 19:05:52 -04:00
parent 8f55626e03
commit 4c1cc50231
68 changed files with 1586 additions and 697 deletions
@@ -1,30 +1,13 @@
'use client';
import ReactGridLayout from 'react-grid-layout';
import { ResponsiveGridLayout, useContainerWidth, verticalCompactor } from 'react-grid-layout';
import type { Layout } from 'react-grid-layout';
import 'react-grid-layout/css/styles.css';
import 'react-resizable/css/styles.css';
// WidthProvider and Responsive are namespace exports from react-grid-layout.
// With @types/react-grid-layout's `export =` pattern, we access them via the module.
const WidthProvider = (
ReactGridLayout as unknown as {
WidthProvider: <P extends React.ComponentType<React.ComponentProps<P>>>(
component: P
) => React.ComponentType<React.ComponentProps<P> & { measureBeforeMount?: boolean }>;
}
).WidthProvider;
const Responsive = (
ReactGridLayout as unknown as {
Responsive: React.ComponentType<ReactGridLayout.ResponsiveProps>;
}
).Responsive;
const ResponsiveGridLayout = WidthProvider(Responsive);
interface ResponsiveGridProps {
layout: ReactGridLayout.Layout[];
onLayoutChange: (newLayout: ReactGridLayout.Layout[]) => void;
layout: Layout;
onLayoutChange: (newLayout: Layout) => void;
children: React.ReactNode;
}
@@ -33,19 +16,26 @@ export default function ResponsiveGrid({
onLayoutChange,
children,
}: ResponsiveGridProps) {
const { width, containerRef, mounted } = useContainerWidth();
return (
<ResponsiveGridLayout
className="layout"
layouts={{ lg: layout }}
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
rowHeight={80}
onLayoutChange={onLayoutChange}
draggableHandle=".widget-drag-handle"
compactType="vertical"
isResizable
>
{children}
</ResponsiveGridLayout>
<div ref={containerRef}>
{mounted && (
<ResponsiveGridLayout
className="layout"
width={width}
layouts={{ lg: layout }}
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
rowHeight={80}
onLayoutChange={(_layout, _layouts) => onLayoutChange(_layout)}
dragConfig={{ handle: '.widget-drag-handle' }}
compactor={verticalCompactor}
resizeConfig={{ enabled: true }}
>
{children}
</ResponsiveGridLayout>
)}
</div>
);
}
@@ -58,7 +58,7 @@ export function ProjectProgressWidget() {
{project.progress}%
</span>
</div>
<Progress value={project.progress} className="h-2" />
<Progress value={project.progress} className="h-2" aria-label={`${project.name} progress: ${project.progress}%`} />
</div>
))}
</div>
@@ -1,15 +1,12 @@
'use client';
import { Plus } from 'lucide-react';
import { useRouter } from 'next/navigation';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
export function QuickAddWidget() {
function handleQuickAdd() {
document.dispatchEvent(
new KeyboardEvent('keydown', { key: 'k', metaKey: true })
);
}
const router = useRouter();
return (
<Card className="h-full border-0 shadow-none">
@@ -25,7 +22,7 @@ export function QuickAddWidget() {
variant="outline"
size="sm"
className="justify-start"
onClick={handleQuickAdd}
onClick={() => router.push('/tasks?new=true')}
>
New task
</Button>
@@ -33,7 +30,7 @@ export function QuickAddWidget() {
variant="outline"
size="sm"
className="justify-start"
onClick={handleQuickAdd}
onClick={() => router.push('/habits?new=true')}
>
New habit
</Button>
@@ -41,7 +38,7 @@ export function QuickAddWidget() {
variant="outline"
size="sm"
className="justify-start"
onClick={handleQuickAdd}
onClick={() => router.push('/notes?new=true')}
>
New note
</Button>