微信支付
This commit is contained in:
@@ -11,6 +11,12 @@ import {
|
||||
type RegionSelection,
|
||||
} from '../lib/region-data';
|
||||
|
||||
type OpenCity = {
|
||||
code: string;
|
||||
name: string;
|
||||
province: string;
|
||||
};
|
||||
|
||||
type StoreItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -25,6 +31,11 @@ type StoreItem = {
|
||||
category?: { name: string } | null;
|
||||
};
|
||||
|
||||
function resolveCityCode(region: RegionSelection, cities: OpenCity[]): string | undefined {
|
||||
if (region.province === REGION_ALL || region.city === REGION_ALL) return undefined;
|
||||
return cities.find((c) => c.province === region.province && c.name === region.city)?.code;
|
||||
}
|
||||
|
||||
const CATEGORY_TABS = ['全部', '火锅', '地方菜', '高端餐饮', '烧烤烤肉', '西餐'] as const;
|
||||
const MOCK_DISTANCES = ['800m', '1.2km', '3.5km', '1.5km', '2.0km'];
|
||||
|
||||
@@ -43,29 +54,56 @@ function formatHours(store: StoreItem) {
|
||||
|
||||
export default function StoreListPage() {
|
||||
const navigate = useNavigate();
|
||||
const [cities, setCities] = useState<OpenCity[]>([]);
|
||||
const [stores, setStores] = useState<StoreItem[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [categoryTab, setCategoryTab] = useState<string>('全部');
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [region, setRegion] = useState<RegionSelection>(DEFAULT_REGION);
|
||||
const [regionPickerOpen, setRegionPickerOpen] = useState(false);
|
||||
|
||||
const cityCode = useMemo(() => resolveCityCode(region, cities), [region, cities]);
|
||||
|
||||
useEffect(() => {
|
||||
request<StoreItem[]>('USER_H5', '/stores?cityCode=410100').then(setStores);
|
||||
request<OpenCity[]>('USER_H5', '/catalog/cities').then(setCities);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
setLoading(true);
|
||||
const qs = cityCode ? `?cityCode=${encodeURIComponent(cityCode)}` : '';
|
||||
request<StoreItem[]>('USER_H5', `/stores${qs}`)
|
||||
.then((data) => {
|
||||
if (!cancelled) setStores(data);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) setStores([]);
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setLoading(false);
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [cityCode]);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
let list = stores;
|
||||
if (categoryTab !== '全部') {
|
||||
list = list.filter((s) => s.category?.name === categoryTab);
|
||||
}
|
||||
list = list.filter((s) => {
|
||||
const province = s.province ?? '河南省';
|
||||
const city = s.cityName ?? '郑州市';
|
||||
if (region.province !== REGION_ALL && province !== region.province) return false;
|
||||
if (region.city !== REGION_ALL && city !== region.city) return false;
|
||||
if (region.district !== REGION_ALL && s.district !== region.district) return false;
|
||||
return true;
|
||||
});
|
||||
if (!cityCode) {
|
||||
list = list.filter((s) => {
|
||||
const province = s.province ?? '河南省';
|
||||
const city = s.cityName ?? '郑州市';
|
||||
if (region.province !== REGION_ALL && province !== region.province) return false;
|
||||
if (region.city !== REGION_ALL && city !== region.city) return false;
|
||||
if (region.district !== REGION_ALL && s.district !== region.district) return false;
|
||||
return true;
|
||||
});
|
||||
} else if (region.district !== REGION_ALL) {
|
||||
list = list.filter((s) => s.district === region.district);
|
||||
}
|
||||
const q = keyword.trim().toLowerCase();
|
||||
if (q) {
|
||||
list = list.filter(
|
||||
@@ -76,7 +114,7 @@ export default function StoreListPage() {
|
||||
);
|
||||
}
|
||||
return list;
|
||||
}, [stores, categoryTab, keyword, region]);
|
||||
}, [stores, categoryTab, keyword, region, cityCode]);
|
||||
|
||||
const regionLabel = formatRegion(region.province, region.city, region.district);
|
||||
|
||||
@@ -123,7 +161,8 @@ export default function StoreListPage() {
|
||||
</header>
|
||||
|
||||
<main className="store-list">
|
||||
{filtered.map((s, index) => (
|
||||
{loading && <div className="store-empty">加载门店中...</div>}
|
||||
{!loading && filtered.map((s, index) => (
|
||||
<article
|
||||
key={s.id}
|
||||
className="store-card"
|
||||
@@ -170,11 +209,11 @@ export default function StoreListPage() {
|
||||
</article>
|
||||
))}
|
||||
|
||||
{filtered.length === 0 && (
|
||||
{!loading && filtered.length === 0 && (
|
||||
<div className="store-empty">{stores.length === 0 ? '暂无门店' : '未找到匹配门店'}</div>
|
||||
)}
|
||||
|
||||
{filtered.length > 0 && (
|
||||
{!loading && filtered.length > 0 && (
|
||||
<p className="store-list-end">没有更多门店了</p>
|
||||
)}
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user