Skip to content

Commit 34734f6

Browse files
committed
feat: 연속 잔디 심기 일 수 표시 구현
1 parent f6bed68 commit 34734f6

1 file changed

Lines changed: 47 additions & 6 deletions

File tree

services/heatmap/dailyStat.service.ts

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
orderBy,
1010
getDoc,
1111
Timestamp,
12+
limit,
13+
updateDoc,
1214
} from 'firebase/firestore';
1315
import { db } from '@/lib/firebase';
1416

@@ -25,12 +27,6 @@ function dateKeyKST(date = new Date()) {
2527
return kst.toISOString().slice(0, 10);
2628
}
2729

28-
const formatDate = (d: string | Date | undefined) => {
29-
if (!d) return '';
30-
if (typeof d === 'string') return d;
31-
return d.toISOString().split('T')[0]; // YYYY-MM-DD 형식
32-
};
33-
3430
export const recomputeDailyStat = async (uid: string) => {
3531
const dateKey = dateKeyKST();
3632

@@ -54,6 +50,10 @@ export const recomputeDailyStat = async (uid: string) => {
5450
/** 3. DailyStat 덮어쓰기 */
5551
const ref = doc(db, 'users', uid, 'dailyStats', dateKey);
5652

53+
/** 4. 연속 잔디 심기 일 수 계산 */
54+
const streakDays = await fetchStreakDays(uid);
55+
await updateDoc(doc(db, 'users', uid), { streakDays });
56+
5757
await setDoc(
5858
ref,
5959
{
@@ -109,3 +109,44 @@ export const fetchDailyStatByDate = async (
109109
total: data.total ?? 0,
110110
};
111111
};
112+
113+
function prevDateKey(key: string) {
114+
const [y, m, d] = key.split('-').map(Number);
115+
// UTC로 만들고 하루 빼서 다시 YYYY-MM-DD
116+
const utc = new Date(Date.UTC(y, m - 1, d));
117+
utc.setUTCDate(utc.getUTCDate() - 1);
118+
return utc.toISOString().slice(0, 10);
119+
}
120+
121+
async function fetchStreakDays(uid: string): Promise<number> {
122+
const todayKey = dateKeyKST();
123+
124+
// 최근 400일 정도만 읽어도 충분 (1년 스트릭 기준)
125+
const statsRef = collection(db, 'users', uid, 'dailyStats');
126+
const q = query(
127+
statsRef,
128+
where('date', '<=', todayKey),
129+
orderBy('date', 'desc'),
130+
limit(400)
131+
);
132+
133+
const snap = await getDocs(q);
134+
135+
// 빠른 조회용 map
136+
const map = new Map<string, number>();
137+
snap.docs.forEach((d) => {
138+
const data = d.data() as DailyStat;
139+
map.set(data.date, data.total ?? 0);
140+
});
141+
142+
const todayTotal = map.get(todayKey) ?? 0;
143+
let cursor = todayTotal > 0 ? todayKey : prevDateKey(todayKey);
144+
145+
let streak = 0;
146+
while ((map.get(cursor) ?? 0) > 0) {
147+
streak += 1;
148+
cursor = prevDateKey(cursor);
149+
}
150+
151+
return streak;
152+
}

0 commit comments

Comments
 (0)