This commit is contained in:
Dominik Klarkowski
2026-06-22 14:28:05 +02:00
parent d908965c95
commit 763321ec68
4 changed files with 51 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { Geist, Geist_Mono, Space_Grotesk } from "next/font/google";
import { Nav } from "@/components/nav";
import { auth } from "@/auth";
import "./globals.css";
@@ -14,6 +14,11 @@ const geistMono = Geist_Mono({
subsets: ["latin"],
});
const spaceGrotesk = Space_Grotesk({
variable: "--font-space-grotesk",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "KNUR - Książka Notowań Udźwigów i Rezultatów",
description: "Analiza treningów biegowych i siłowych",
@@ -29,7 +34,7 @@ export default async function RootLayout({
return (
<html
lang="pl"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
className={`${geistSans.variable} ${geistMono.variable} ${spaceGrotesk.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col bg-bg text-fg">
{session && <Nav />}

View File

@@ -14,6 +14,8 @@ import {
isSameMonth,
isSameDay,
isToday,
isAfter,
startOfDay,
} from "date-fns";
import { pl } from "date-fns/locale";
import { Activity, ChevronLeft, ChevronRight, Dumbbell, Sparkles } from "lucide-react";
@@ -64,9 +66,16 @@ export function DashboardAnalysisCard({ analyses, runs, workouts }: Props) {
const [currentMonth, setCurrentMonth] = useState(() => new Date());
const [selectedDate, setSelectedDate] = useState<Date>(() => new Date());
function hasAnalysis(date: Date) {
return byDay.has(dayKey(date));
}
const runDays = useMemo(
() => new Set(runs.map((r) => dayKey(new Date(r.startTime)))),
[runs]
);
const workoutDays = useMemo(
() => new Set(workouts.map((w) => dayKey(new Date(w.date)))),
[workouts]
);
const todayStart = startOfDay(new Date());
const monthStart = startOfMonth(currentMonth);
const monthEnd = endOfMonth(monthStart);
@@ -142,12 +151,17 @@ export function DashboardAnalysisCard({ analyses, runs, workouts }: Props) {
<div className="grid grid-cols-7 gap-1">
{days.map((d, i) => {
const key = dayKey(d);
const inMonth = isSameMonth(d, monthStart);
const has = hasAnalysis(d);
const today = isToday(d);
const selectable = has || today;
const future = isAfter(startOfDay(d), todayStart);
const selectable = !future;
const selected = isSameDay(d, selectedDate);
const hasRun = runDays.has(key);
const hasWorkout = workoutDays.has(key);
const hasAnalysis = byDay.has(key);
return (
<button
type="button"
@@ -159,21 +173,37 @@ export function DashboardAnalysisCard({ analyses, runs, workouts }: Props) {
!inMonth && "opacity-30",
selectable && !selected && "cursor-pointer text-fg hover:bg-accent/20",
selected && "bg-accent font-semibold text-fg",
!selectable && "cursor-default text-fg/40",
!selectable && "cursor-not-allowed text-fg/30",
today && !selected && "ring-1 ring-accent/50",
]
.filter(Boolean)
.join(" ")}
>
{d.getDate()}
{has && !selected && (
<span className="absolute bottom-0.5 left-1/2 h-1 w-1 -translate-x-1/2 rounded-full bg-accent" />
{!selected && (hasRun || hasWorkout || hasAnalysis) && (
<span className="absolute bottom-0.5 left-1/2 flex -translate-x-1/2 gap-0.5">
{hasRun && <span className="h-1 w-1 rounded-full bg-[#5b9bd5]" />}
{hasWorkout && <span className="h-1 w-1 rounded-full bg-[#70ad47]" />}
{hasAnalysis && <span className="h-1 w-1 rounded-full bg-accent" />}
</span>
)}
</button>
);
})}
</div>
<div className="mt-3 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-fg/55">
<span className="flex items-center gap-1">
<span className="h-1.5 w-1.5 rounded-full bg-[#5b9bd5]" /> Bieg
</span>
<span className="flex items-center gap-1">
<span className="h-1.5 w-1.5 rounded-full bg-[#70ad47]" /> Siłownia
</span>
<span className="flex items-center gap-1">
<span className="h-1.5 w-1.5 rounded-full bg-accent" /> Analiza
</span>
</div>
<div className="mt-4 flex flex-col gap-1.5">
<p className="text-xs font-medium text-fg/50">
Treningi · {format(selectedDate, "d MMM yyyy", { locale: pl })}
@@ -250,7 +280,7 @@ export function DashboardAnalysisCard({ analyses, runs, workouts }: Props) {
</p>
) : (
<p className="text-sm text-fg/60">
Wybierz dzień oznaczony kropką, aby zobaczyć analizę z tego dnia.
Brak analizy AI dla {format(selectedDate, "d MMMM yyyy", { locale: pl })}.
</p>
)}
</div>

View File

@@ -24,17 +24,15 @@ export async function Nav() {
<Link href="/" className="flex items-center gap-3 text-lg font-bold text-fg">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="/logo.svg"
src="/logo-icon.svg"
alt=""
width={72}
height={72}
className="-mt-1 -mb-6 h-[72px] w-[72px] rounded-2xl shadow-lg ring-2 ring-surface"
/>
<span className="hidden text-xs font-normal tracking-wide text-fg/50 sm:block">
<span className="font-semibold text-accent">K</span>siążka{" "}
<span className="font-semibold text-accent">N</span>otowań{" "}
<span className="font-semibold text-accent">U</span>dźwigów i{" "}
<span className="font-semibold text-accent">R</span>ezultatów
<span className="hidden text-2xl tracking-tight text-white [font-family:var(--font-space-grotesk)] sm:block">
<span className="font-bold [-webkit-text-stroke:0.7px_white]">KNUR</span>
<span className="font-medium text-accent">.APP</span>
</span>
</Link>
<nav className="flex items-center gap-1 sm:gap-2">

1
public/logo-icon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 4.9 KiB