登录页面
This commit is contained in:
@@ -1,35 +1,182 @@
|
||||
import { View, Text, Button } from '@tarojs/components';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useDidShow } from '@tarojs/taro';
|
||||
import TabMainHeader from '../../components/TabMainHeader';
|
||||
import PageShell from '../../components/PageShell';
|
||||
import UserTabBar, { shouldRenderPageTabBar, syncTabBarSelected } from '../../components/UserTabBar';
|
||||
import { isLoggedIn } from '../../lib/api';
|
||||
import { goLogin } from '../../lib/auth-nav';
|
||||
import { isLoggedIn, request, toast } from '../../lib/api';
|
||||
import { navBarStyle, useNavBarMetrics } from '../../lib/nav-bar';
|
||||
|
||||
type BenefitSummary = {
|
||||
totalBalance: number;
|
||||
maxRedeemAmount: number;
|
||||
activeCouponCount: number;
|
||||
};
|
||||
|
||||
type CouponItem = {
|
||||
id: string;
|
||||
couponNo: string;
|
||||
totalAmount: number;
|
||||
usedAmount: number;
|
||||
balance: number;
|
||||
status: string;
|
||||
sourceProduct: string;
|
||||
};
|
||||
|
||||
function formatMoney(amount: number) {
|
||||
return amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||||
}
|
||||
|
||||
function usagePercent(coupon: CouponItem) {
|
||||
const total = Number(coupon.totalAmount);
|
||||
if (total <= 0) return 0;
|
||||
return Math.min(100, Math.round((Number(coupon.usedAmount) / total) * 100));
|
||||
}
|
||||
|
||||
export default function BenefitPage() {
|
||||
const metrics = useNavBarMetrics();
|
||||
const loggedIn = isLoggedIn();
|
||||
const [summary, setSummary] = useState<BenefitSummary | null>(null);
|
||||
const [coupons, setCoupons] = useState<CouponItem[]>([]);
|
||||
const [tab, setTab] = useState<'available' | 'history'>('available');
|
||||
|
||||
useDidShow(() => {
|
||||
syncTabBarSelected(2);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!loggedIn) return;
|
||||
Promise.all([
|
||||
request<BenefitSummary>('/benefit/summary'),
|
||||
request<CouponItem[]>('/benefit/coupons'),
|
||||
])
|
||||
.then(([s, list]) => {
|
||||
setSummary(s);
|
||||
setCoupons(Array.isArray(list) ? list : []);
|
||||
})
|
||||
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'));
|
||||
}, [loggedIn]);
|
||||
|
||||
const available = coupons.filter((c) => c.status === 'ACTIVE' && c.balance > 0);
|
||||
const history = coupons.filter((c) => c.status === 'USED_UP' || c.status === 'VOID');
|
||||
const visible = tab === 'available' ? available : history;
|
||||
|
||||
return (
|
||||
<View className="u-page u-page--tab">
|
||||
<TabMainHeader title="好客权益" />
|
||||
<View className="u-card">
|
||||
{loggedIn ? (
|
||||
<View className="u-empty">权益列表将在后续迭代接入</View>
|
||||
) : (
|
||||
<View>
|
||||
<View className="u-empty">登录后查看好客权益余额</View>
|
||||
<Button
|
||||
className="u-btn u-btn--block"
|
||||
onClick={() => Taro.navigateTo({ url: '/pages/login/index' })}
|
||||
>
|
||||
去登录
|
||||
</Button>
|
||||
<PageShell variant="tab" className="benefit-page">
|
||||
<View className="benefit-header" style={navBarStyle(metrics)}>
|
||||
<View
|
||||
className="benefit-header__content"
|
||||
style={{ height: `${metrics.navContentHeight}px` }}
|
||||
>
|
||||
<View className="benefit-header-city">
|
||||
<View className="benefit-header-city-pin" />
|
||||
<Text>郑州市</Text>
|
||||
</View>
|
||||
)}
|
||||
<Text className="benefit-header-title">好客权益</Text>
|
||||
<View className="benefit-header-btn" onClick={() => toast('消息通知即将开放')}>
|
||||
<Text>🔔</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{!loggedIn ? (
|
||||
<View className="benefit-login-gate">
|
||||
<View className="u-empty">登录后查看好客权益余额</View>
|
||||
<View
|
||||
className="u-btn u-btn--block"
|
||||
style={{ maxWidth: 240, margin: '0 auto' }}
|
||||
onClick={() => goLogin('/pages/benefit/index')}
|
||||
>
|
||||
<Text>去登录</Text>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View className="benefit-main">
|
||||
<View className="benefit-hero">
|
||||
<View className="benefit-hero-top">
|
||||
<View>
|
||||
<Text className="benefit-hero-label">当前好客权益余额</Text>
|
||||
<View className="benefit-hero-amount">
|
||||
<Text className="benefit-hero-symbol">¥</Text>
|
||||
<Text className="benefit-hero-value">
|
||||
{summary ? formatMoney(summary.totalBalance) : '--'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className="benefit-hero-logo">
|
||||
<Text>康</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className="benefit-hero-actions">
|
||||
<Text
|
||||
className="benefit-hero-link"
|
||||
onClick={() => Taro.navigateTo({ url: '/pages/benefit-detail/index' })}
|
||||
>
|
||||
查看权益明细 ›
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
className="benefit-hero-cta"
|
||||
onClick={() => Taro.navigateTo({ url: '/pages/redeem/index' })}
|
||||
>
|
||||
<Text>去使用</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="benefit-tabs">
|
||||
<Text
|
||||
className={`benefit-tab${tab === 'available' ? ' benefit-tab--active' : ''}`}
|
||||
onClick={() => setTab('available')}
|
||||
>
|
||||
可用权益
|
||||
</Text>
|
||||
<Text
|
||||
className={`benefit-tab${tab === 'history' ? ' benefit-tab--active' : ''}`}
|
||||
onClick={() => setTab('history')}
|
||||
>
|
||||
历史记录
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{visible.length === 0 ? (
|
||||
<View className="u-empty">{tab === 'available' ? '暂无可用权益' : '暂无历史记录'}</View>
|
||||
) : (
|
||||
visible.map((c) => (
|
||||
<View key={c.id} className="benefit-coupon">
|
||||
<View className="benefit-coupon-notch" />
|
||||
<View className="benefit-coupon-notch benefit-coupon-notch--right" />
|
||||
<View className="benefit-coupon-head">
|
||||
<Text className="benefit-coupon-name">{c.sourceProduct || '好客权益'}</Text>
|
||||
<Text className="benefit-coupon-balance">¥{formatMoney(c.balance)}</Text>
|
||||
</View>
|
||||
<Text className="benefit-coupon-no">NO. {c.couponNo}</Text>
|
||||
<View className="benefit-progress">
|
||||
<View className="benefit-progress-bar" style={{ width: `${usagePercent(c)}%` }} />
|
||||
</View>
|
||||
<View className="benefit-coupon-footer">
|
||||
<Text className="benefit-coupon-meta">
|
||||
已用 ¥{formatMoney(c.usedAmount)} / 总额 ¥{formatMoney(c.totalAmount)}
|
||||
</Text>
|
||||
{tab === 'available' ? (
|
||||
<Text
|
||||
className="benefit-coupon-btn"
|
||||
onClick={() =>
|
||||
Taro.navigateTo({
|
||||
url: `/pages/redeem/index?couponId=${c.id}&amount=${c.balance}`,
|
||||
})
|
||||
}
|
||||
>
|
||||
立即核销
|
||||
</Text>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
|
||||
{shouldRenderPageTabBar() ? <UserTabBar selected={2} /> : null}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user