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:
@@ -18,9 +18,9 @@
|
||||
.filter((model) => {
|
||||
const matchesSearch =
|
||||
searchQuery === "" ||
|
||||
model.artist_name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
model.tags.some((tag) => tag.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
const matchesCategory = categoryFilter === "all" || model.category === categoryFilter;
|
||||
model.artist_name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
model.tags?.some((tag) => tag.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
const matchesCategory = categoryFilter === "all";
|
||||
return matchesSearch && matchesCategory;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
@@ -31,7 +31,7 @@
|
||||
// }
|
||||
// if (sortBy === "rating") return b.rating - a.rating;
|
||||
// if (sortBy === "videos") return b.videos - a.videos;
|
||||
return a.artist_name.localeCompare(b.artist_name);
|
||||
return (a.artist_name ?? "").localeCompare(b.artist_name ?? "");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -205,7 +205,7 @@
|
||||
<!-- Stats -->
|
||||
<div class="flex items-center justify-between text-sm text-muted-foreground mb-4">
|
||||
<!-- <span>{model.videos} videos</span> -->
|
||||
<span class="capitalize">{model.category}</span>
|
||||
<!-- category not available -->
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
const { data } = $props();
|
||||
|
||||
let images = $derived(
|
||||
data.model.photos.map((p) => ({
|
||||
(data.model.photos ?? []).map((p) => ({
|
||||
...p,
|
||||
url: getAssetUrl(p.id),
|
||||
thumbnail: getAssetUrl(p.id, "thumbnail"),
|
||||
@@ -29,7 +29,7 @@
|
||||
</script>
|
||||
|
||||
<Meta
|
||||
title={data.model.artist_name}
|
||||
title={data.model.artist_name ?? ""}
|
||||
description={data.model.description}
|
||||
image={getAssetUrl(data.model.avatar, "medium")!}
|
||||
/>
|
||||
@@ -44,7 +44,7 @@
|
||||
{#if data.model.banner}
|
||||
<img
|
||||
src={getAssetUrl(data.model.banner, "banner")}
|
||||
alt={$_(data.model.artist_name)}
|
||||
alt={data.model.artist_name ?? ""}
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user