@@ -0,0 +1,115 @@
+import type { FC } from 'react';
+import { useEffect, useRef, useState } from 'react';
+
+import { formatTool } from '@iap/kit-util';
+import dayjs from 'dayjs';
+
+import {
+ useRedeemCodeViewModel,
+ selectRedeemRecords,
+ selectRedeemLoading,
+} from '@/app/(viewmodels)/redeemCodeViewModel';
+
+interface RecordsDialogProps {
+ closeDialog?: () => void;
+}
+
+/**
+ * 移动端兑换记录弹窗组件
+ * 图三设计:可滚动加载的兑换历史
+ */
+const RecordsDialog: FC<RecordsDialogProps> = () => {
+ const records = useRedeemCodeViewModel(selectRedeemRecords);
+ const loading = useRedeemCodeViewModel(selectRedeemLoading);
+ const { getRecords } = useRedeemCodeViewModel();
+
+ const containerRef = useRef<HTMLDivElement>(null);
+ const [showGradient, setShowGradient] = useState(false);
+
+ const checkGradient = () => {
+ const el = containerRef.current;
+ if (!el) return;
+ const hasScroll = el.scrollHeight > el.clientHeight;
+ const atBottom = el.scrollHeight - el.scrollTop <= el.clientHeight + 2;
+ setShowGradient(hasScroll && !atBottom);
+ };
+
+ useEffect(() => {
+ getRecords();
+ }, []);
+
+ useEffect(() => {
+ checkGradient();
+ }, [records]);
+
+ return (
+ <div className='bg-[#24282F] rounded-[20px] xs:rounded-[32px] py-[20px] xs:py-[32px]'>
+ {/* 标题 */}
+ <p className='text-white text-[24px] xs:text-[36px] font-[800] mb-[20px] text-center'>Redeem History</p>
+ {/* 表头 */}
+ <div className='h-[88px] leading-[56px] flex bg-[#1A1D24] text-center text-[28px] text-white/20 font-[800]'>
+ <span className='py-[16px] flex-1'>TIME</span>
+ <span className=' flex-1 relative py-[16px] before:absolute before:left-0 before:top-0 before:h-full before:w-[1px] before:bg-white/10 after:absolute after:right-0 after:top-0 after:h-full after:w-[1px] after:bg-white/10'>
+ REWARD
+ </span>
+ <span className='py-[16px] w-[262px]'>CODE</span>
+ </div>
+ {/* 可滚动列表 */}
+ <div className='relative'>
+ <div ref={containerRef} onScroll={checkGradient} className='h-[500px] overflow-y-auto'>
+ {records.length === 0 && !loading ? (
+ <div className='flex items-center justify-center h-full text-white/50 text-[36px] font-[800]'>
+ No data available.
+ </div>
+ ) : (
+ <div className='text-[24px] font-[roboto] font-[600]'>
+ {records.map((record, index) => (
+ <div
+ key={`${record.promoCode}-${index}`}
+ className={`flex py-[16px] ${index % 2 === 1 ? 'bg-[#1F222A]' : ''}`}
+ >
+ {/* 时间列 */}
+ <span className='flex-1 flex flex-col text-center'>
+ <span className='text-white/50'>
+ {dayjs.unix(record.createTime / 1000).format('MM/DD/YYYY')}
+ </span>
+ <span className='text-white/50'>
+ {dayjs.unix(record.createTime / 1000).format('HH:mm:ss')}
+ </span>
+ </span>
+
+ {/* 奖励列 */}
+ <span className='flex-1 flex flex-col text-center'>
+ <span className='text-[#FFA600] font-[800]'>
+ GC {formatTool.ToKMBTUnitString(record.gc, 2)}
+ </span>
+ <span className='text-[#0DCC73] font-[800]'>SC {record.sc}</span>
+ </span>
+
+ {/* 兑换码列 */}
+ <span className='text-white/50 text-center break-all px-[14px] flex items-center w-[262px] justify-center'>
+ {record.promoCode}
+ </span>
+ </div>
+ ))}
+ </div>
+ )}
+ </div>
+ {showGradient && (
+ <div
+ className='absolute bottom-0 left-0 right-0 h-[80px] pointer-events-none'
+ style={{ background: 'linear-gradient(0deg, #24282F 0%, rgba(36, 40, 47, 0.00) 100%)' }}
+ />
+ )}
+ </div>
+
+ {/* 底部说明 */}
+ <div className='mt-[32px] text-[28px] text-white/50 space-y-[4px] px-[32px] font-[700] font-[roboto]'>
+ <p>1. Save up to 50 past redemption records.</p>
+ <p>2. For any issues, contact our customer support.</p>
+ </div>
+ </div>
+ );
+};
+
+export default RecordsDialog;