diff --git a/.phase12-state.json b/.phase12-state.json index d170731..ddb0b52 100644 --- a/.phase12-state.json +++ b/.phase12-state.json @@ -1,8 +1,9 @@ { "completed_features": [], - "current_feature": "time-rounding-rules", + "current_feature": "user-avatars", "started_at": "2026-05-23T06:33:48.406343", "attempted_features": [ - "invoicing-stub" + "invoicing-stub", + "time-rounding-rules" ] } \ No newline at end of file diff --git a/GENERATION_LOG.md b/GENERATION_LOG.md index 0622fef..6358375 100644 --- a/GENERATION_LOG.md +++ b/GENERATION_LOG.md @@ -1478,3 +1478,22 @@ src/index.ts(27,25): error TS2769: No overload matches this call. Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTy +- `06:36:29` **INFO** Committed feature time-rounding-rules +- `06:36:29` **INFO** Pushed: rc=0 + +## Phase-3 Feature: user-avatars (2026-05-23 06:36:29) + +- `06:36:29` **INFO** Description: Avatar-Component (Initialen-Badge) + überall einsetzen +- `06:36:29` **INFO** Generating apps/web/src/components/Avatar.tsx (Avatar-Component. Props: name (string), size? ('sm'|'md'|'lg', default…) +- `06:36:41` **INFO** wrote 1067 chars in 12.0s (attempt 1) +- `06:36:41` **INFO** Generating apps/web/src/components/Nav.tsx (ERWEITERT — füge links neben Log…) +- `06:37:38` **INFO** wrote 6000 chars in 56.9s (attempt 1) +- `06:37:38` **INFO** Running tsc --noEmit on api… +- `06:37:40` **WARN** tsc errors: +src/index.ts(27,25): error TS2769: No overload matches this call. + Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. + Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTypeProvider>, opts: { ...; }, done: (err?: Error | undefined) => void): void'. + Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. + Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTy diff --git a/apps/web/src/components/Avatar.tsx b/apps/web/src/components/Avatar.tsx new file mode 100644 index 0000000..f4840c1 --- /dev/null +++ b/apps/web/src/components/Avatar.tsx @@ -0,0 +1,45 @@ +import React from 'react'; + +interface AvatarProps { + name: string; + size?: 'sm' | 'md' | 'lg'; +} + +const COLORS = [ + 'bg-orange-500', + 'bg-blue-500', + 'bg-emerald-500', + 'bg-purple-500', + 'bg-pink-500', +]; + +const SIZE_MAP = { + sm: 'w-8 h-8 text-xs', + md: 'w-10 h-10 text-sm', + lg: 'w-12 h-12 text-base', +}; + +export const Avatar: React.FC = ({ name, size = 'md' }) => { + const getInitials = (name: string) => { + const parts = name.trim().split(/\s+/); + if (parts.length === 1) return parts[0].substring(0, 2).toUpperCase(); + return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase(); + }; + + const getColor = (name: string) => { + let hash = 0; + for (let i = 0; i < name.length; i++) { + hash = name.charCodeAt(i) + ((hash << 5) - hash); + } + const index = Math.abs(hash) % COLORS.length; + return COLORS[index]; + }; + + return ( +
+ {getInitials(name)} +
+ ); +}; \ No newline at end of file diff --git a/apps/web/src/components/Nav.tsx b/apps/web/src/components/Nav.tsx index a264243..f724278 100644 --- a/apps/web/src/components/Nav.tsx +++ b/apps/web/src/components/Nav.tsx @@ -15,11 +15,13 @@ import { X, Zap, CreditCard, - Languages + Languages, + LogOut } from "lucide-react" import { useQuery } from "@tanstack/react-query" import { api } from "../lib/api" import { useTheme } from "../lib/theme" +import Avatar from "./Avatar" export default function Nav() { const location = useLocation() @@ -96,7 +98,7 @@ export default function Nav() { -
+
- + +
+ {user && ( + + )} + +
+