feat: 新增连续记账天数统计与热力图展示功能
This commit is contained in:
96
src/services/streakService.ts
Normal file
96
src/services/streakService.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Streak Service - API calls for user streak management
|
||||
* 连续记账功能服务
|
||||
*/
|
||||
|
||||
import api from './api';
|
||||
import type { ApiResponse } from '../types';
|
||||
|
||||
/**
|
||||
* Streak info returned from backend
|
||||
*/
|
||||
export interface StreakInfo {
|
||||
current_streak: number; // 当前连续天数
|
||||
longest_streak: number; // 最长连续记录
|
||||
total_record_days: number; // 累计记账天数
|
||||
has_record_today: boolean; // 今天是否已记账
|
||||
message: string; // 提示信息
|
||||
}
|
||||
|
||||
/**
|
||||
* Daily contribution data
|
||||
*/
|
||||
export interface DailyContribution {
|
||||
date: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Streak info in camelCase for frontend
|
||||
*/
|
||||
export interface StreakInfoFormatted {
|
||||
currentStreak: number;
|
||||
longestStreak: number;
|
||||
totalRecordDays: number;
|
||||
hasRecordToday: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map streak data from API (snake_case) to frontend (camelCase)
|
||||
*/
|
||||
function mapStreakFromApi(data: StreakInfo): StreakInfoFormatted {
|
||||
return {
|
||||
currentStreak: data.current_streak,
|
||||
longestStreak: data.longest_streak,
|
||||
totalRecordDays: data.total_record_days,
|
||||
hasRecordToday: data.has_record_today,
|
||||
message: data.message,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current user's streak info
|
||||
* 获取当前用户的连续记账信息
|
||||
*/
|
||||
export async function getStreakInfo(): Promise<StreakInfoFormatted> {
|
||||
const response = await api.get<ApiResponse<StreakInfo>>('/user/streak');
|
||||
if (!response.data) {
|
||||
// Return default values if no streak data
|
||||
return {
|
||||
currentStreak: 0,
|
||||
longestStreak: 0,
|
||||
totalRecordDays: 0,
|
||||
hasRecordToday: false,
|
||||
message: '开始记录你的第一笔账吧!',
|
||||
};
|
||||
}
|
||||
return mapStreakFromApi(response.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate streak from transaction history
|
||||
* 重新计算连续记账天数(基于交易历史)
|
||||
*/
|
||||
export async function recalculateStreak(): Promise<StreakInfoFormatted> {
|
||||
const response = await api.post<ApiResponse<StreakInfo>>('/user/streak/recalculate');
|
||||
if (!response.data) {
|
||||
throw new Error(response.error || 'Failed to recalculate streak');
|
||||
}
|
||||
return mapStreakFromApi(response.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get daily contribution data for heatmap
|
||||
* 获取热力图数据
|
||||
*/
|
||||
export async function getContributionData(): Promise<DailyContribution[]> {
|
||||
const response = await api.get<ApiResponse<DailyContribution[]>>('/user/streak/contribution');
|
||||
return response.data || [];
|
||||
}
|
||||
|
||||
export default {
|
||||
getStreakInfo,
|
||||
recalculateStreak,
|
||||
getContributionData,
|
||||
};
|
||||
Reference in New Issue
Block a user