Revisi untuk fix performance issues dan UI bugs setelah Revision 11.
| # | Issue | Severity |
|---|---|---|
| 1 | Stuck "Drawing...", sphere tidak berhenti, confetti muncul tapi winner tidak reveal | 🔴 Critical |
| 2 | Reveal animation laggy setelah page 1 (page 2, 3, dst) | 🟡 Medium |
| 3 | Confirm masih butuh 2x klik | 🟡 Medium |
| 4 | History page butuh improvement (pagination, search, cancelled table) | 🟢 Enhancement |
| 5 | Winner tidak muncul di History sampai Ctrl+F5 | 🔴 Critical |
| 6 | Tombol Confirm muncul padahal ada cancelled winner | 🔴 Critical |
| 7 | Performance: void coupon sangat lambat (sequential) | 🔴 Critical |
┌─────────────────────────────────────────────────────────────────┐
│ UNTUK SETIAP ISSUE: │
│ │
│ 1. ANALISA ROOT CAUSE │
│ - Cari code yang terkait │
│ - Identifikasi mengapa bug terjadi │
│ - Tampilkan code snippet yang bermasalah │
│ │
│ 2. BUAT PLAN │
│ - Files yang akan dimodifikasi │
│ - Perubahan yang akan dilakukan │
│ │
│ 3. TUNGGU APPROVAL dari user │
│ │
│ 4. EKSEKUSI setelah approved │
└─────────────────────────────────────────────────────────────────┘
- Klik Start Draw → Klik Stop Draw
- Tombol berubah ke "Drawing..." dan disabled
- Sphere tetap berputar, tidak berhenti
- Tidak ada winner yang ter-reveal
- Tiba-tiba confetti muncul
- Side panel progress bertambah
[CouponRepo] Voided coupon: howxpwagl5xk9z
[CouponRepo] Voided coupon: 7734kkvodoajsg
[CouponRepo] Voided coupon: 0lq1y972f50730
... (sangat lambat per line)
- Cari flow dari Stop button → draw() → void coupon
- Identifikasi apakah void dilakukan sequential (
awaitdalam loop) - Check apakah UI state update menunggu semua void selesai
- Check apakah sphere rotation ter-pause saat drawing
- Sequential
await couponRepository.void()dalam loop - UI thread ter-block karena menunggu semua DB operations
- State
'drawing'tidak transition ke'revealing'sampai semua void selesai
- Batch void operations (single transaction)
- Atau parallel void dengan
Promise.all() - Update UI state sebelum void operations
- Show winners dulu, void di background
- Page 1 reveal animation smooth
- Batch 50 winners, 10 per page = 5 pages
- Page 2, 3, 4, 5 terasa laggy
- Confetti muncul setelah page 1
- Console log:
[DrawScreen] Revealed: 50 / 50di akhir
Ketika mencapai reveal terakhir (50/50), laggy hilang
- Cari animation logic di
WinnerRevealAnimation.tsx - Check apakah animation interval berjalan untuk SEMUA 50 cards
- Check apakah animation hanya perlu untuk visible page (10 cards)
- Animation loop iterasi untuk semua 50 cards, bukan hanya 10 visible
setRevealedCountdipanggil 50x, menyebabkan 50x re-render
- Hanya animasikan cards di current visible page
- Cards di page lain langsung tampil tanpa animation
- Atau: animate semua tapi dengan requestAnimationFrame/batch updates
- Klik Confirm pertama → tidak ada respon
- Klik Confirm kedua → baru proceed
- Check
handleConfirmfunction - Check
state.statussaat Confirm diklik (harusnya'reviewing') - Check apakah
REVEAL_COMPLETEsudah dispatch sebelum Confirm available - Add console.log untuk debug
- Klik pertama: status masih
'revealing', guard condition return early onRevealCompletetidak terpanggil atau terlambat- Race condition antara animation complete dan button click
- Pastikan
onRevealCompletedipanggil setelah animation selesai - Atau: auto-transition setelah timeout
- Atau: relax guard condition
-
Per-prize table dengan pagination
- Setiap prize punya table terpisah
- Pagination untuk table besar
-
Cancelled/Invalid winners table
- Table terpisah untuk cancelled winners
- Show cancel reason
-
Search functionality
- Search by participant name
- Search by coupon ID
- Search across all winners
- Check current History page structure
- Identify components yang perlu dibuat/modified
- Check data fetching logic
- Create
PrizeWinnersTablecomponent dengan pagination - Create
CancelledWinnersTablecomponent - Add search input dengan filter logic
- Update History page layout
- Confirm winners di Draw screen
- Buka History page di tab lain
- Winners tidak muncul
- Harus Ctrl+F5 (hard refresh) baru muncul
- Check React Query cache settings
- Check apakah
invalidateQueriesdipanggil setelah confirm - Check query key untuk history page
- Check apakah cache stale time terlalu lama
- React Query cache tidak ter-invalidate setelah confirm
- History page query menggunakan cached data
- Tidak ada refetch on focus/mount
queryClient.invalidateQueries(['winners'])setelah confirm- Set
staleTime: 0untuk winners query - Atau:
refetchOnMount: 'always'
- Ada cancelled winners di batch
- Tombol Confirm tetap muncul
- Seharusnya: hanya Redraw All yang muncul
- Check button rendering logic di
DrawControls.tsx - Check kondisi untuk show Confirm vs Redraw All
- Check bagaimana cancelled winners di-detect
if (hasCancelledWinners) {
show: [Redraw All]
} else {
show: [Confirm]
}
hasCancelledWinnerstidak dihitung dengan benar- Logic salah:
&&vs|| - Cancelled winners dari batch sebelumnya tidak di-reset
- Fix cancelled winner detection
- Ensure Confirm ONLY shows when ALL winners valid
- Draw 50 winners
- Console log void coupon sangat lambat (1 per second atau lebih)
- Total blocking time: 50+ seconds
[CouponRepo] Voided coupon: xxx
(long pause)
[CouponRepo] Voided coupon: yyy
(long pause)
...
- Check
draw()function - bagaimana void dipanggil - Check
couponRepository.void()implementation - Check apakah ada index di IndexedDB untuk coupon.id
- Check apakah ada transaction overhead
// Sequential - SLOW!
for (const coupon of selectedCoupons) {
await couponRepository.void(eventId, coupon.id)
}// Option A: Single transaction with batch modify
await db.transaction('rw', db.coupons, async () => {
const couponIds = selectedCoupons.map(c => c.id)
await db.coupons
.where('id')
.anyOf(couponIds)
.modify({ status: 'void' })
})
// Option B: Parallel with Promise.all (less efficient but simpler)
await Promise.all(
selectedCoupons.map(c => couponRepository.void(eventId, c.id))
)- Participants: 1,540
- Coupons: 148,705
- Some participants have 1000+ coupons
- Win rule:
limitedwithmaxWins: 2
Ketika participant mencapai maxWins, SEMUA kupon participant di-void.
- Participant dengan 1000 kupon → 1000 kupon di-void sekaligus
- Ini expected behavior untuk performance pool query
- Namun perlu optimize batch operation
Batch 9: [Draw] Active coupons count: 89807
Expected: 148,705 - (8 × 50) = 148,305
Actual: 89,807
Missing: ~59,000 coupons (voided via voidByParticipantId)
Ini expected karena beberapa participant besar sudah mencapai maxWins.
| File | Issues |
|---|---|
src/services/drawService.ts |
#1, #7 - batch void operations |
src/repositories/couponRepository.ts |
#7 - batch void method |
src/components/draw/WinnerRevealAnimation.tsx |
#2 - visible page only animation |
src/components/draw/DrawControls.tsx |
#3, #6 - button logic |
src/pages/DrawScreen.tsx |
#1, #3, #5 - state management, cache invalidation |
src/pages/History.tsx |
#4 - pagination, search, tables |
src/components/history/PrizeWinnersTable.tsx |
#4 - new component |
src/components/history/CancelledWinnersTable.tsx |
#4 - new component |
src/hooks/useWinners.ts |
#5 - query settings |
1. Issue #7 (Performance) - karena mempengaruhi #1
↓
2. Issue #1 (Stuck Drawing) - critical UX
↓
3. Issue #6 (Confirm dengan Cancelled) - logic error
↓
4. Issue #3 (Confirm 2x klik) - UX
↓
5. Issue #2 (Animation laggy) - performance
↓
6. Issue #5 (Cache invalidation) - data freshness
↓
7. Issue #4 (History enhancement) - new feature
- Draw 50 winners selesai dalam < 5 detik
- UI tidak stuck di "Drawing..."
- Sphere berhenti saat stop diklik
- Winners reveal segera setelah draw selesai
- Page 1 animation smooth
- Page 2+ tidak laggy
- Cards di page lain sudah revealed saat navigate
- Confirm hanya butuh 1x klik
- Console log: status = 'reviewing' saat klik
- Setiap prize punya table terpisah
- Pagination berfungsi
- Cancelled winners table ada
- Search berfungsi (by name, by coupon)
- Confirm di tab A
- Refresh tab B (bukan Ctrl+F5)
- Winners muncul di tab B
- Ada cancelled → hanya Redraw All
- Semua valid → hanya Confirm
- Tidak ada Confirm + Cancelled bersamaan