Skip to content

feat: multilingual admin broadcast/announcement system#28

Merged
kemalcalak merged 17 commits into
mainfrom
broadcast
Jun 14, 2026
Merged

feat: multilingual admin broadcast/announcement system#28
kemalcalak merged 17 commits into
mainfrom
broadcast

Conversation

@kemalcalak

Copy link
Copy Markdown
Owner

No description provided.

@kemalcalak kemalcalak self-assigned this Jun 14, 2026
@kemalcalak

Copy link
Copy Markdown
Owner Author

/review — 10 bulgu

1. Göreli ../ import — @/ alias kullanılmalı

Dosya: src/app/[locale]/admin/(protected)/broadcasts/BroadcastsContent.tsx#L9
Kategori: review-md-compliance · Önem: major

AdminForbidden, "../AdminForbidden" göreli yoluyla import ediliyor. REVIEW.md §3.1/§4.7 proje içi tüm importlarda @/ alias'ını zorunlu kılar; ../ yasak.

§4.7: "Relative ../ import — @/ zorunlu."

Öneri: import { AdminForbidden } from "@/app/[locale]/admin/(protected)/AdminForbidden"; olarak değiştir.


2. JsonValueAnnouncementFields güvensiz as cast

Dosya: src/components/common/notification-text.ts#L38-L39
Kategori: bug · Önem: major

item.data.variables ve item.data.translations (tip: JsonValue) narrowing yapılmadan doğrudan as AnnouncementFields[...] ile dönüştürülüyor. REVIEW.md §5.8 bu tür zorlama cast'leri flag'liyor; beklenmedik biçimli payload sessiz hata üretir.

variables: item.data.variables as AnnouncementFields["variables"],

Öneri: data alanını Zod ile (safeParse) doğrulayıp narrowing sonrası kullan; ham as cast'ini kaldır.


3. zodFieldRule bypass'ı — template_key için manuel required

Dosya: src/components/admin/broadcasts/BroadcastComposer.tsx#L136
Kategori: review-md-compliance · Önem: major

template_key Form.Item'ı { required: true, message: t('validation:required') } manuel kuralı kullanıyor. REVIEW.md §5.5 uyarınca rules, zodFieldRule(getXSchema(tv)) ile doldurulmalı; Zod köprüsünü atlayan manuel kural validation standardını kırar.

§5.5: "Manuel rule'la zodFieldRule bypass'ı."

Öneri: schemas/announcement.ts'e getTemplateKeySchema(tv) ekle ve rules={[zodFieldRule(getTemplateKeySchema(tv))]} kullan.


4. zodFieldRule bypass'ı — role_filter için manuel required

Dosya: src/components/admin/broadcasts/BroadcastComposer.tsx#L167
Kategori: review-md-compliance · Önem: major

role_filter Form.Item'ı da manuel { required: true, message: ... } kuralı kullanıyor. REVIEW.md §3.7 validation mesajının schema dışında yazılamayacağını, §5.5 ise zodFieldRule zorunluluğunu belirtir.

§3.7: "Validation mesajı schema dışında hardcode edilmez."

Öneri: getRoleFilterSchema(tv) factory'si ekle ve zodFieldRule aracılığıyla kullan.


5. useSendBroadcast aktif banner cache'ini invalidate etmiyor

Dosya: src/hooks/api/use-broadcasts.ts#L36-L43
Kategori: bug · Önem: minor

onSuccess yalnızca broadcastKeys.all (["broadcasts"]) prefix'ini invalidate ediyor; broadcastKeys.activeAnnouncement (["announcements","active"]) farklı prefix olduğu için kapsanmıyor. show_banner: true ile gönderilen duyuru, WebSocket bildirimi gelene veya 5 dk staleTime dolana kadar admin'e görünmez.

queryClient.invalidateQueries({ queryKey: broadcastKeys.all });

Öneri: onSuccess içine queryClient.invalidateQueries({ queryKey: broadcastKeys.activeAnnouncement }) ekle.


6. Props interface ismi PropsAnnouncementPreviewProps olmalı

Dosya: src/components/admin/broadcasts/AnnouncementPreview.tsx#L17-L23
Kategori: review-md-compliance · Önem: major

Props interface'i interface Props olarak tanımlanmış. REVIEW.md §3.1/§5.8 interface <ComponentName>Props şablonunu zorunlu kılar. Aynı kalıp PR #20/#22/#24/#27 review'larında defalarca reddedildi.

§5.8: "Inline ({a, b}: {a:string}) props — interface XProps zorunlu."

Öneri: interface Propsinterface AnnouncementPreviewProps olarak yeniden adlandır.


7. Props interface ismi PropsCustomLanguageFieldsProps olmalı

Dosya: src/components/admin/broadcasts/CustomLanguageFields.tsx#L16-L18
Kategori: review-md-compliance · Önem: major

Props interface'i interface Props olarak bırakılmış; bileşen adını taşımıyor. REVIEW.md §5.8 interface <ComponentName>Props gerektirir.

§5.8: "interface XProps zorunlu."

Öneri: interface Propsinterface CustomLanguageFieldsProps olarak yeniden adlandır.


8. Props interface ismi PropsTemplateVariableFieldsProps olmalı

Dosya: src/components/admin/broadcasts/TemplateVariableFields.tsx#L16-L19
Kategori: review-md-compliance · Önem: major

Bu dosyada da aynı interface Props kalıbı var. REVIEW.md §5.8 bileşen adını taşıyan named interface zorunluluğu getirir.

§5.8: "interface XProps zorunlu."

Öneri: interface Propsinterface TemplateVariableFieldsProps olarak yeniden adlandır.


9. İç bileşen props ismi StripPropsBannerStripProps olmalı

Dosya: src/components/common/AnnouncementBanner.tsx#L35-L40
Kategori: review-md-compliance · Önem: minor

BannerStrip iç bileşeninin props interface'i interface StripProps. REVIEW.md §3.1/§5.8 interface <ComponentName>Props şablonunu iç bileşenler için de zorunlu kılar.

§3.1: "Props: interface <ComponentName>Props."

Öneri: interface StripPropsinterface BannerStripProps olarak yeniden adlandır.


10. İç bileşen props ismi SheetPropsBannerSheetProps olmalı

Dosya: src/components/common/AnnouncementBanner.tsx#L97-L100
Kategori: review-md-compliance · Önem: minor

BannerSheet iç bileşeninin props interface'i interface SheetProps extends StripProps. REVIEW.md §3.1/§5.8 named interface şablonunu gerektirir.

§3.1: "Props: interface <ComponentName>Props."

Öneri: interface SheetProps extends StripPropsinterface BannerSheetProps extends BannerStripProps olarak güncelle.


🤖 Generated with Claude Code

@kemalcalak

Copy link
Copy Markdown
Owner Author

/review — takip: 10/10 bulgu çözüldü ✅

Önceki review'daki 10 bulgunun tamamı giderildi (yerelde uygulandı, tsc --noEmit ile doğrulandı — kaynak dosyalarda tip hatası yok):

# Bulgu Çözüm
1 Göreli ../AdminForbidden import @/ alias'a çevrildi
2 notification-text.ts güvensiz as cast Zod safeParse + narrowing şemaları, hatalı payload'da undefined fallback
3 template_key manuel required zodFieldRule(getTemplateKeySchema(t))
4 role_filter manuel required zodFieldRule(getRoleFilterSchema(t))
5 activeAnnouncement invalidate eksik onSuccess'e ikinci invalidateQueries eklendi
6 PropsAnnouncementPreviewProps named interface
7 PropsCustomLanguageFieldsProps named interface
8 PropsTemplateVariableFieldsProps named interface
9 StripPropsBannerStripProps named interface
10 SheetPropsBannerSheetProps named interface (extends dahil güncellendi)

Eklenen yorumlar "ne" değil "neden" açıklıyor; yeni narrowing şemaları (z.record(key, value)) Zod 4 ve mevcut notification.ts ile uyumlu.

🤖 Generated with Claude Code

@kemalcalak kemalcalak merged commit b370c55 into main Jun 14, 2026
2 checks passed
@kemalcalak kemalcalak deleted the broadcast branch June 14, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant