feat: add shared @sexy.pivoine.art/types package and fix type safety across frontend/backend
- Create packages/types with shared TypeScript domain model interfaces (User, Video, Model, Article, Comment, Recording, etc.) - Wire both frontend and backend packages to use @sexy.pivoine.art/types via workspace:* - Update backend Pothos objectRef types to use shared interfaces instead of inline types - Update frontend $lib/types.ts to re-export from shared package - Fix all type errors introduced by more accurate nullable types (avatar/banner as string|null UUIDs, author nullable, events/device_info as object[]) - Add artist_name to comment user select in backend resolver - Widen utility function signatures (getAssetUrl, getUserInitials, calcReadingTime) to accept null/undefined Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
<Meta
|
||||
title={displayName}
|
||||
description={data.user.description || `${displayName}'s profile`}
|
||||
image={data.user.avatar ? getAssetUrl(data.user.avatar, "thumbnail") : undefined}
|
||||
image={data.user.avatar ? getAssetUrl(data.user.avatar, "thumbnail") ?? undefined : undefined}
|
||||
/>
|
||||
|
||||
<div class="relative min-h-screen bg-gradient-to-br from-background via-primary/5 to-accent/5">
|
||||
@@ -91,12 +91,7 @@
|
||||
>
|
||||
</div>
|
||||
|
||||
{#if data.user.location}
|
||||
<div class="flex items-center gap-2 text-muted-foreground mb-4">
|
||||
<span class="icon-[ri--map-pin-line] w-4 h-4"></span>
|
||||
<span>{data.user.location}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if data.user.description}
|
||||
<p class="text-muted-foreground mb-4">
|
||||
@@ -148,7 +143,7 @@
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
|
||||
<div class="text-center p-4 rounded-lg bg-accent/10">
|
||||
<div class="text-3xl font-bold text-primary">
|
||||
{Math.round(data.gamification.stats.total_weighted_points)}
|
||||
{Math.round(data.gamification.stats.total_weighted_points ?? 0)}
|
||||
</div>
|
||||
<div class="text-sm text-muted-foreground mt-1">
|
||||
{$_("gamification.points")}
|
||||
@@ -188,7 +183,7 @@
|
||||
{$_("gamification.achievements")} ({data.gamification.achievements.length})
|
||||
</h3>
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-3">
|
||||
{#each data.gamification.achievements as achievement (achievement.id)}
|
||||
{#each (data.gamification?.achievements ?? []) as achievement (achievement.id)}
|
||||
<div
|
||||
class="flex flex-col items-center gap-2 p-3 rounded-lg bg-accent/10 border border-border/30 hover:border-primary/50 transition-colors"
|
||||
title={achievement.description}
|
||||
@@ -199,7 +194,7 @@
|
||||
</span>
|
||||
{#if achievement.date_unlocked}
|
||||
<span class="text-xs text-muted-foreground">
|
||||
{new Date(achievement.date_unlocked).toLocaleDateString($locale)}
|
||||
{new Date(achievement.date_unlocked).toLocaleDateString($locale ?? undefined)}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user