11import {
22 doc ,
3- runTransaction ,
4- serverTimestamp ,
3+ setDoc ,
54 collection ,
65 getDocs ,
76 query ,
87 where ,
8+ serverTimestamp ,
99 orderBy ,
1010 getDoc ,
11+ Timestamp ,
1112} from 'firebase/firestore' ;
1213import { db } from '@/lib/firebase' ;
1314
1415export interface DailyStat {
1516 date : string ; // YYYY-MM-DD
16- total : number ;
17- }
18-
19- export type DailyStatDetail = {
20- date : string ;
2117 tilCount : number ;
22- todoDoneCount : number ;
18+ planDoneCount : number ;
2319 total : number ;
24- } ;
20+ updatedAt ?: Timestamp ;
21+ }
2522
2623function dateKeyKST ( date = new Date ( ) ) {
2724 const kst = new Date ( date . getTime ( ) + 9 * 60 * 60 * 1000 ) ;
2825 return kst . toISOString ( ) . slice ( 0 , 10 ) ;
2926}
3027
31- export const bumpDailyStat = async (
32- uid : string ,
33- deltaTil : number ,
34- deltaTodoDone : number
35- ) => {
36- const key = dateKeyKST ( ) ;
37- const ref = doc ( db , `users/${ uid } /dailyStats/${ key } ` ) ;
38-
39- await runTransaction ( db , async ( tx ) => {
40- const snap = await tx . get ( ref ) ;
41-
42- const prev = snap . exists ( )
43- ? ( snap . data ( ) as {
44- tilCount ?: number ;
45- todoDoneCount ?: number ;
46- total ?: number ;
47- } )
48- : { } ;
49-
50- const nextTil = Math . max ( 0 , ( prev . tilCount ?? 0 ) + deltaTil ) ;
51- const nextTodo = Math . max ( 0 , ( prev . todoDoneCount ?? 0 ) + deltaTodoDone ) ;
52- const nextTotal = Math . max ( 0 , nextTil + nextTodo ) ;
53-
54- tx . set (
55- ref ,
56- {
57- date : key ,
58- tilCount : nextTil ,
59- todoDoneCount : nextTodo ,
60- total : nextTotal ,
61- updatedAt : serverTimestamp ( ) ,
62- } ,
63- { merge : true }
64- ) ;
65- } ) ;
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+
34+ export const recomputeDailyStat = async ( uid : string ) => {
35+ const dateKey = dateKeyKST ( ) ;
36+
37+ /** 1. 오늘 완료된 planItems */
38+
39+ const planItemsRef = collection ( db , 'users' , uid , 'planItems' ) ;
40+ const planQuery = query (
41+ planItemsRef ,
42+ where ( 'dateKey' , '==' , dateKey ) ,
43+ where ( 'isChecked' , '==' , true )
44+ ) ;
45+ const planSnap = await getDocs ( planQuery ) ;
46+ const planDoneCount = planSnap . size ;
47+
48+ /** 2. 오늘 작성한 TIL */
49+ const tilRef = collection ( db , 'users' , uid , 'tils' ) ;
50+ const tilQuery = query ( tilRef , where ( 'dateKey' , '==' , dateKey ) ) ;
51+ const tilSnap = await getDocs ( tilQuery ) ;
52+ const tilCount = tilSnap . size ;
53+
54+ /** 3. DailyStat 덮어쓰기 */
55+ const ref = doc ( db , 'users' , uid , 'dailyStats' , dateKey ) ;
56+
57+ await setDoc (
58+ ref ,
59+ {
60+ date : dateKey ,
61+ tilCount,
62+ planDoneCount,
63+ total : tilCount + planDoneCount ,
64+ updatedAt : serverTimestamp ( ) ,
65+ } ,
66+ { merge : true }
67+ ) ;
6668} ;
6769
6870export const fetchDailyStats = async ( uid : string ) : Promise < DailyStat [ ] > => {
6971 const colRef = collection ( db , 'users' , uid , 'dailyStats' ) ;
7072
71- const endDate = dateKeyKST ( new Date ( ) ) ;
72- const startDate = ( ( ) => {
73- const d = new Date ( ) ;
74- d . setFullYear ( d . getFullYear ( ) - 1 ) ;
75- d . setDate ( d . getDate ( ) + 1 ) ;
76- return dateKeyKST ( d ) ;
77- } ) ( ) ;
73+ const endDate = dateKeyKST ( ) ;
74+ const start = new Date ( ) ;
75+ start . setFullYear ( start . getFullYear ( ) - 1 ) ;
76+ const startDate = dateKeyKST ( start ) ;
7877
7978 const q = query (
8079 colRef ,
@@ -85,21 +84,18 @@ export const fetchDailyStats = async (uid: string): Promise<DailyStat[]> => {
8584
8685 const snap = await getDocs ( q ) ;
8786
88- return snap . docs . map ( ( doc ) => {
89- const data = doc . data ( ) ;
90- return {
91- date : data . date ,
92- tilCount : data . tilCount ?? 0 ,
93- todoDoneCount : data . todoDoneCount ?? 0 ,
94- total : data . total ?? 0 ,
95- } ;
96- } ) ;
87+ return snap . docs . map ( ( d ) => ( {
88+ date : d . data ( ) . date ,
89+ tilCount : d . data ( ) . tilCount ?? 0 ,
90+ planDoneCount : d . data ( ) . planDoneCount ?? 0 ,
91+ total : d . data ( ) . total ?? 0 ,
92+ } ) ) ;
9793} ;
9894
9995export const fetchDailyStatByDate = async (
10096 uid : string ,
101- date : string // YYYY-MM-DD
102- ) : Promise < DailyStatDetail | null > => {
97+ date : string
98+ ) : Promise < DailyStat | null > => {
10399 const ref = doc ( db , 'users' , uid , 'dailyStats' , date ) ;
104100 const snap = await getDoc ( ref ) ;
105101
@@ -109,7 +105,7 @@ export const fetchDailyStatByDate = async (
109105 return {
110106 date : data . date ,
111107 tilCount : data . tilCount ?? 0 ,
112- todoDoneCount : data . todoDoneCount ?? 0 ,
108+ planDoneCount : data . planDoneCount ?? 0 ,
113109 total : data . total ?? 0 ,
114110 } ;
115111} ;
0 commit comments