141 lines
4.4 KiB
TypeScript
141 lines
4.4 KiB
TypeScript
'use client';
|
||
|
||
import { useGetSevenDaysSignList, useSignIn } from '@/hooks/useHome';
|
||
import { SignInListOutput } from '@/services/home/types';
|
||
import { useQueryClient } from '@tanstack/react-query';
|
||
import { homeKeys } from '@/lib/query-keys';
|
||
import { CheckInCard } from './CheckInCard';
|
||
import { useEffect, useRef } from 'react';
|
||
import { toast } from 'sonner';
|
||
|
||
export function CheckInGrid() {
|
||
const queryClient = useQueryClient();
|
||
const { data: signListData, isLoading } = useGetSevenDaysSignList();
|
||
const signInMutation = useSignIn();
|
||
const hasSignRef = useRef(false);
|
||
|
||
useEffect(() => {
|
||
const initializeCheckIn = async () => {
|
||
if (hasSignRef.current) return;
|
||
hasSignRef.current = true;
|
||
try {
|
||
// 先进行签到
|
||
const resp = await signInMutation.mutateAsync();
|
||
if (resp) {
|
||
toast.success('Check-in Successful!');
|
||
}
|
||
// 签到成功后再获取列表数据
|
||
await queryClient.invalidateQueries({
|
||
queryKey: homeKeys.getSevenDaysSignList(),
|
||
});
|
||
await queryClient.invalidateQueries({
|
||
queryKey: ['wallet'],
|
||
});
|
||
} catch (error) {
|
||
console.error('初始化签到失败:', error);
|
||
// 即使签到失败,也要获取列表数据显示界面
|
||
queryClient.invalidateQueries({
|
||
queryKey: homeKeys.getSevenDaysSignList(),
|
||
});
|
||
queryClient.invalidateQueries({
|
||
queryKey: ['wallet'],
|
||
});
|
||
}
|
||
};
|
||
|
||
if (signListData) {
|
||
initializeCheckIn();
|
||
}
|
||
}, [signListData]);
|
||
|
||
if (isLoading) {
|
||
return (
|
||
<div className="grid h-[328px] grid-cols-3 grid-rows-2 gap-4">
|
||
{Array.from({ length: 6 }).map((_, index) => (
|
||
<div
|
||
key={index}
|
||
className="animate-pulse rounded-[16px] border border-[rgba(251,222,255,0.2)] bg-[#282233]"
|
||
/>
|
||
))}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
const signList = signListData?.list || [];
|
||
const today = new Date();
|
||
const todayStr = today.toISOString().split('T')[0]; // yyyy-MM-dd 格式
|
||
|
||
// 确保有7天的数据,如果不足则补充默认数据
|
||
const fullSignList: (SignInListOutput & { day: number })[] = Array.from(
|
||
{ length: 7 },
|
||
(_, index) => {
|
||
const day = index + 1;
|
||
const existingData = signList.find((item, itemIndex) => itemIndex === index);
|
||
|
||
return {
|
||
day,
|
||
coinNum: existingData?.coinNum || [5, 10, 15, 20, 30, 50, 80][index],
|
||
dayStr: existingData?.dayStr || '',
|
||
signIn: existingData?.signIn || false,
|
||
};
|
||
}
|
||
);
|
||
|
||
// 找到今天应该签到的是第几天
|
||
const todayIndex = fullSignList.findIndex((item) => {
|
||
if (!item.dayStr) return false;
|
||
return item.dayStr === todayStr;
|
||
});
|
||
|
||
// 如果没有找到今天的数据,假设是按顺序签到,找到第一个未签到的
|
||
const currentDayIndex =
|
||
todayIndex >= 0 ? todayIndex : fullSignList.findIndex((item) => !item.signIn);
|
||
|
||
return (
|
||
<div className="grid grid-cols-4 grid-rows-2 gap-4">
|
||
{fullSignList.map((item, index) => {
|
||
if (index === 3) {
|
||
return (
|
||
<CheckInCard
|
||
key={fullSignList[6].day}
|
||
day={fullSignList[6].day}
|
||
coinNum={fullSignList[6].coinNum || 0}
|
||
signIn={fullSignList[6].signIn || false}
|
||
isToday={fullSignList[6].dayStr === todayStr}
|
||
loading={signInMutation.isPending}
|
||
className="col-span-1 row-span-2"
|
||
/>
|
||
);
|
||
}
|
||
if (index < 3) {
|
||
return (
|
||
<CheckInCard
|
||
key={item.day}
|
||
day={item.day}
|
||
coinNum={item.coinNum || 0}
|
||
signIn={item.signIn || false}
|
||
isToday={index === currentDayIndex}
|
||
loading={signInMutation.isPending}
|
||
className="col-span-1 row-span-1"
|
||
/>
|
||
);
|
||
} else {
|
||
return (
|
||
<CheckInCard
|
||
key={fullSignList[index - 1].day}
|
||
day={fullSignList[index - 1].day}
|
||
coinNum={fullSignList[index - 1].coinNum || 0}
|
||
signIn={fullSignList[index - 1].signIn || false}
|
||
isToday={fullSignList[index - 1].dayStr === todayStr}
|
||
loading={signInMutation.isPending}
|
||
className="col-span-1 row-span-1"
|
||
/>
|
||
);
|
||
}
|
||
})}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default CheckInGrid;
|