Files
stats/apps/start/src/components/profiles/profile-activity.tsx
Carl-Gerhard Lindesvärd 81a7e5d62e feat: dashboard v2, esm, upgrades (#211)
* esm

* wip

* wip

* wip

* wip

* wip

* wip

* subscription notice

* wip

* wip

* wip

* fix envs

* fix: update docker build

* fix

* esm/types

* delete dashboard :D

* add patches to dockerfiles

* update packages + catalogs + ts

* wip

* remove native libs

* ts

* improvements

* fix redirects and fetching session

* try fix favicon

* fixes

* fix

* order and resize reportds within a dashboard

* improvements

* wip

* added userjot to dashboard

* fix

* add op

* wip

* different cache key

* improve date picker

* fix table

* event details loading

* redo onboarding completely

* fix login

* fix

* fix

* extend session, billing and improve bars

* fix

* reduce price on 10M
2025-10-16 12:27:44 +02:00

93 lines
2.4 KiB
TypeScript

import { Widget, WidgetBody } from '@/components/widget';
import { cn } from '@/utils/cn';
import {
addMonths,
eachDayOfInterval,
endOfMonth,
format,
formatISO,
isSameMonth,
startOfMonth,
subMonths,
} from 'date-fns';
import { ActivityIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react';
import { useState } from 'react';
import {
WidgetAbsoluteButtons,
WidgetHead,
WidgetTitle,
} from '../overview/overview-widget';
import { Button } from '../ui/button';
type Props = {
data: { count: number; date: string }[];
};
const MonthCalendar = ({
month,
data,
}: { month: Date; data: Props['data'] }) => (
<div>
<div className="mb-2 text-sm">{format(month, 'MMMM yyyy')}</div>
<div className="-m-1 grid grid-cols-7 gap-1 p-1">
{eachDayOfInterval({
start: startOfMonth(month),
end: endOfMonth(month),
}).map((date) => {
const hit = data.find((item) =>
item.date.includes(formatISO(date, { representation: 'date' })),
);
return (
<div
key={date.toISOString()}
className={cn(
'aspect-square w-full rounded',
hit ? 'bg-highlight' : 'bg-def-200',
)}
/>
);
})}
</div>
</div>
);
export const ProfileActivity = ({ data }: Props) => {
const [startDate, setStartDate] = useState(startOfMonth(new Date()));
return (
<Widget className="w-full">
<WidgetHead className="row justify-between relative">
<WidgetTitle icon={ActivityIcon}>Activity</WidgetTitle>
<WidgetAbsoluteButtons>
<Button
variant="outline"
size="icon"
onClick={() => setStartDate(subMonths(startDate, 1))}
>
<ChevronLeftIcon size={14} />
</Button>
<Button
variant="outline"
size="icon"
disabled={isSameMonth(startDate, new Date())}
onClick={() => setStartDate(addMonths(startDate, 1))}
>
<ChevronRightIcon size={14} />
</Button>
</WidgetAbsoluteButtons>
</WidgetHead>
<WidgetBody>
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
{[3, 2, 1, 0].map((offset) => (
<MonthCalendar
key={offset}
month={subMonths(startDate, offset)}
data={data}
/>
))}
</div>
</WidgetBody>
</Widget>
);
};