51 lines
3.5 KiB
TypeScript
51 lines
3.5 KiB
TypeScript
import { useState } from 'react'
|
||
import Taro from '@tarojs/taro'
|
||
import { Button, Image, Text, View } from '@tarojs/components'
|
||
import { AppTabBar } from '../../components/AppTabBar'
|
||
import { TiangongHeader, TiangongMockNote, TiangongModal } from '../../components/TiangongUI'
|
||
import { deityCatalog, isTiangongDemo, tiangongMock, tiangongSession } from '../../services/tiangong'
|
||
import { resolveAssetUrl } from '../../services/request'
|
||
import { useTiangongSnapshot } from '../../hooks/useTiangongSnapshot'
|
||
import { DeityId } from '../../utils/tiangongMock'
|
||
import { hasLoginAccess } from '../../services/loginAccess'
|
||
import { useRequiredLogin } from '../../hooks/useRequiredLogin'
|
||
import { TiangongLoginGate } from '../../components/TiangongLoginGate'
|
||
import './index.scss'
|
||
|
||
export default function FortunePage() {
|
||
const auth = useRequiredLogin()
|
||
if (auth.status !== 'allowed' || !hasLoginAccess()) return <TiangongLoginGate status={auth.status === 'allowed' ? 'denied' : auth.status} retry={auth.retry} tab />
|
||
return <FortuneContent />
|
||
}
|
||
|
||
function FortuneContent() {
|
||
const snapshot = useTiangongSnapshot()
|
||
const items = deityCatalog.map(item => ({ ...item, ...snapshot.deities[item.id] }))
|
||
const [selected, setSelected] = useState<DeityId | null>(null)
|
||
const [settings, setSettings] = useState(false)
|
||
const open = (id: DeityId, invite = false) => Taro.navigateTo({ url: `/pages/tiangong-detail/index?id=${id}${invite ? '&mode=invite' : ''}` })
|
||
return <View className='tiangong-page'>
|
||
<TiangongHeader title='天宫' /><TiangongMockNote />
|
||
{snapshot.loading && !snapshot.ready && <Text className='tg-data-note'>正在加载神仙列表…</Text>}
|
||
{snapshot.error && <View className='tg-data-note'><Text>{snapshot.error}</Text><Button onClick={() => tiangongSession.refresh(true).catch(() => {})}>重新加载</Button></View>}
|
||
<View className='deity-grid'>
|
||
{items.map(item => <View className='deity-card-wrap' key={item.id}>
|
||
<Button disabled={item.available === false} className={`deity-card ${item.unlocked ? 'unlocked' : 'locked'}`} aria-label={`${item.name},${item.unlocked ? '已恭请' : '未恭请'}`} onClick={() => item.unlocked ? open(item.id) : setSelected(selected === item.id ? null : item.id)}>
|
||
<Image className='deity-image' src={resolveAssetUrl(item.iconUrl) || item.icon} mode='aspectFill' /><Text className='deity-name'>{item.name}{item.available === false && snapshot.ready ? '(暂未配置)' : ''}</Text>
|
||
</Button>
|
||
{selected === item.id && !item.unlocked && <View className='deity-invite-prompt'>
|
||
<Button className='deity-prompt-close' aria-label='关闭恭请提示' onClick={() => setSelected(null)}>×</Button>
|
||
<Text>您还未恭请此神</Text><Text>是否恭请</Text>
|
||
<Button className='deity-invite-button' onClick={() => { setSelected(null); open(item.id, true) }}>恭请</Button>
|
||
</View>}
|
||
</View>)}
|
||
</View>
|
||
{isTiangongDemo() && <Button className='tg-demo-settings' onClick={() => setSettings(true)}>Mock 演示设置</Button>}
|
||
{settings && <TiangongModal title='Mock 演示设置' onClose={() => setSettings(false)} variant='plain'>
|
||
<Text className='tg-modal-title'>Mock 演示设置</Text><Text className='tg-modal-caption'>仅重置本次演示,不修改真实供奉记录。</Text>
|
||
<View className='tg-modal-actions'><Button className='tg-button' onClick={() => { tiangongMock.reset(); setSelected(null); setSettings(false) }}>重置全部演示</Button></View>
|
||
</TiangongModal>}
|
||
<AppTabBar active='fortune' />
|
||
</View>
|
||
}
|