Ausgangspunkt war die Beobachtung zu isVerified (siehe Diskussion). Nachprüfung zeigt: das Problem ist nicht auf isVerified beschränkt, sondern ein wiederkehrendes Muster an zwei Stellen.
Derselbe Block (Verified-Häkchen + Sponsor-Sparkle inkl. isActiveSponsor()-Aufruf) ist copy-paste in mehreren Dateien, jeweils mit leicht anderer Icon-Größe (h-3 / h-3.5 / h-4) und teils anderem aria-label:
src/app/(app)/pets/[petId]/edit/page.tsx:188-190 (nur Verified, ohne Sponsor)
src/app/p/[secret]/users/page.tsx:266-282 (Admin-Toggle-Button, eigene Variante mit conditional fill)
Kein gemeinsamer <PetIdentityBadges>/<VerifiedBadge>-Component, obwohl src/components/ui/pet-avatar.tsx als natürlicher Platz dafür bereits existiert. Die Logik (isActiveSponsor() in src/lib/sponsor.ts) ist sauber zentralisiert — nur das Rendering wurde nie extrahiert.
Kein Schnellschuss — es folgt ein separater Plan für einen sauberen, skalierbaren Refactor (gemeinsame <PetIdentityBadges>-Komponente + petCardSelect-Konstante), bevor neue Features (z. B. das in diesem Issue angedachte "Tierheim"-Badge) dieselben Stellen ein weiteres Mal anfassen.
## DRY-Audit: Befund
Ausgangspunkt war die Beobachtung zu `isVerified` (siehe Diskussion). Nachprüfung zeigt: das Problem ist nicht auf `isVerified` beschränkt, sondern ein wiederkehrendes Muster an zwei Stellen.
### Befund 1 — "Verified + Sponsor Badge"-JSX-Block 4x dupliziert
Derselbe Block (Verified-Häkchen + Sponsor-Sparkle inkl. `isActiveSponsor()`-Aufruf) ist copy-paste in mehreren Dateien, jeweils mit leicht anderer Icon-Größe (`h-3` / `h-3.5` / `h-4`) und teils anderem `aria-label`:
- `src/components/feed/PostCard.tsx:249-266`
- `src/app/(app)/pets/[petId]/page.tsx:74-88`
- `src/components/layout/Sidebar.tsx:151-177` (2x: activePet + Liste)
- `src/components/layout/MobileNav.tsx:109-133` (2x: activePet + Liste)
- `src/app/(app)/pets/[petId]/edit/page.tsx:188-190` (nur Verified, ohne Sponsor)
- `src/app/p/[secret]/users/page.tsx:266-282` (Admin-Toggle-Button, eigene Variante mit conditional fill)
Kein gemeinsamer `<PetIdentityBadges>`/`<VerifiedBadge>`-Component, obwohl `src/components/ui/pet-avatar.tsx` als natürlicher Platz dafür bereits existiert. Die *Logik* (`isActiveSponsor()` in `src/lib/sponsor.ts`) ist sauber zentralisiert — nur das **Rendering** wurde nie extrahiert.
### Befund 2 — Prisma-`select`-Fragment dupliziert
```
{ nickname, avatarKey, isVerified, owner: { select: { sponsorSince, sponsorPeriodEnd } } }
```
identisch in `feed.ts:34-37`, `feed.ts:51-54`, `explore.ts:82-85`, `pets.ts:127`. Kein shared `petCardSelect`-Konstante — jede Query tippt das Select-Fragment neu.
### Zum Vergleich: was sauber ist
- `assertPetOwnership()` / `assertAdmin()` — zentralisiert, konsistent in 22 Dateien verwendet.
- `isActiveSponsor()` — Logik zentral in `src/lib/sponsor.ts`.
- Spider-Exclusion & denormalisierte Reaction/Comment/Repost-Counter — laut `CLAUDE.md` bewusste, dokumentierte Ausnahmen (kein Bug, akzeptierter Trade-off).
### Nächster Schritt
Kein Schnellschuss — es folgt ein separater Plan für einen sauberen, skalierbaren Refactor (gemeinsame `<PetIdentityBadges>`-Komponente + `petCardSelect`-Konstante), bevor neue Features (z. B. das in diesem Issue angedachte "Tierheim"-Badge) dieselben Stellen ein weiteres Mal anfassen.
Beide Teile umgesetzt, verifiziert (tsc + vitest + Build) und deployed:
Teil A — src/repositories/pet-repository.ts (petIdentitySelect/petCardSelect), ~38 Fundstellen in 13 Router-Dateien migriert. Commit e0c887c.
Teil B — src/components/ui/pet-identity-badges.tsx, 6 Fundstellen in 5 Dateien migriert. Commit 3d8c473.
Gepusht nach Gitea, auf dem NAS via Rolling-Deploy ausgerollt (alle 3 Replicas, zero downtime), Live-Site bestätigt gesund. Schließe das Issue.
## Erledigt
Beide Teile umgesetzt, verifiziert (tsc + vitest + Build) und deployed:
- **Teil A** — `src/repositories/pet-repository.ts` (`petIdentitySelect`/`petCardSelect`), ~38 Fundstellen in 13 Router-Dateien migriert. Commit `e0c887c`.
- **Teil B** — `src/components/ui/pet-identity-badges.tsx`, 6 Fundstellen in 5 Dateien migriert. Commit `3d8c473`.
Gepusht nach Gitea, auf dem NAS via Rolling-Deploy ausgerollt (alle 3 Replicas, zero downtime), Live-Site bestätigt gesund. Schließe das Issue.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Im Gespräch mit Claude, kam heraus das wir einige Probleme im Code haben, diese sollen bereinigt werden.
DRY-Audit: Befund
Ausgangspunkt war die Beobachtung zu
isVerified(siehe Diskussion). Nachprüfung zeigt: das Problem ist nicht aufisVerifiedbeschränkt, sondern ein wiederkehrendes Muster an zwei Stellen.Befund 1 — "Verified + Sponsor Badge"-JSX-Block 4x dupliziert
Derselbe Block (Verified-Häkchen + Sponsor-Sparkle inkl.
isActiveSponsor()-Aufruf) ist copy-paste in mehreren Dateien, jeweils mit leicht anderer Icon-Größe (h-3/h-3.5/h-4) und teils anderemaria-label:src/components/feed/PostCard.tsx:249-266src/app/(app)/pets/[petId]/page.tsx:74-88src/components/layout/Sidebar.tsx:151-177(2x: activePet + Liste)src/components/layout/MobileNav.tsx:109-133(2x: activePet + Liste)src/app/(app)/pets/[petId]/edit/page.tsx:188-190(nur Verified, ohne Sponsor)src/app/p/[secret]/users/page.tsx:266-282(Admin-Toggle-Button, eigene Variante mit conditional fill)Kein gemeinsamer
<PetIdentityBadges>/<VerifiedBadge>-Component, obwohlsrc/components/ui/pet-avatar.tsxals natürlicher Platz dafür bereits existiert. Die Logik (isActiveSponsor()insrc/lib/sponsor.ts) ist sauber zentralisiert — nur das Rendering wurde nie extrahiert.Befund 2 — Prisma-
select-Fragment dupliziertidentisch in
feed.ts:34-37,feed.ts:51-54,explore.ts:82-85,pets.ts:127. Kein sharedpetCardSelect-Konstante — jede Query tippt das Select-Fragment neu.Zum Vergleich: was sauber ist
assertPetOwnership()/assertAdmin()— zentralisiert, konsistent in 22 Dateien verwendet.isActiveSponsor()— Logik zentral insrc/lib/sponsor.ts.CLAUDE.mdbewusste, dokumentierte Ausnahmen (kein Bug, akzeptierter Trade-off).Nächster Schritt
Kein Schnellschuss — es folgt ein separater Plan für einen sauberen, skalierbaren Refactor (gemeinsame
<PetIdentityBadges>-Komponente +petCardSelect-Konstante), bevor neue Features (z. B. das in diesem Issue angedachte "Tierheim"-Badge) dieselben Stellen ein weiteres Mal anfassen.Erledigt
Beide Teile umgesetzt, verifiziert (tsc + vitest + Build) und deployed:
src/repositories/pet-repository.ts(petIdentitySelect/petCardSelect), ~38 Fundstellen in 13 Router-Dateien migriert. Commite0c887c.src/components/ui/pet-identity-badges.tsx, 6 Fundstellen in 5 Dateien migriert. Commit3d8c473.Gepusht nach Gitea, auf dem NAS via Rolling-Deploy ausgerollt (alle 3 Replicas, zero downtime), Live-Site bestätigt gesund. Schließe das Issue.