fix(services): resolve owner shop from backend
This commit is contained in:
@@ -20,13 +20,12 @@ import {
|
||||
listPlayers,
|
||||
updatePlayerService,
|
||||
} from "@/lib/api"
|
||||
import { resolveOwnerShop } from "@/lib/domain/resolve-current-shop"
|
||||
import { toApiError } from "@/lib/errors"
|
||||
import { GameIcon } from "@/lib/game-icons"
|
||||
import { useMyShop } from "@/lib/hooks/use-my-shop"
|
||||
import { notifyInfo, notifySuccess } from "@/lib/toast"
|
||||
import type { Game, PlayerService } from "@/lib/types"
|
||||
import { useAuthStore } from "@/store/auth"
|
||||
import { useShopStore } from "@/store/shops"
|
||||
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema"
|
||||
import { ArrowLeft } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
@@ -51,11 +50,14 @@ export default function NewServicePage() {
|
||||
const serviceId = searchParams.get("serviceId")
|
||||
const userId = useAuthStore((state) => state.user?.id)
|
||||
const currentRole = useAuthStore((state) => state.currentRole)
|
||||
const shops = useShopStore((state) => state.shops)
|
||||
const {
|
||||
shop: ownerShop,
|
||||
loading: shopLoading,
|
||||
error: shopError,
|
||||
} = useMyShop(currentRole === "owner")
|
||||
const [players, setPlayers] = useState<Awaited<ReturnType<typeof listPlayers>>>([])
|
||||
const [editingService, setEditingService] = useState<PlayerService | undefined>(undefined)
|
||||
const [loadingService, setLoadingService] = useState(Boolean(serviceId))
|
||||
const ownerShop = resolveOwnerShop(userId, shops)
|
||||
const scopedPlayerIds =
|
||||
currentRole === "player"
|
||||
? userId
|
||||
@@ -156,10 +158,14 @@ export default function NewServicePage() {
|
||||
}
|
||||
}, [])
|
||||
|
||||
if (loadingService) {
|
||||
if (loadingService || (currentRole === "owner" && shopLoading)) {
|
||||
return <div className="text-sm text-muted-foreground">加载中...</div>
|
||||
}
|
||||
|
||||
if (currentRole === "owner" && shopError) {
|
||||
return <div className="text-sm text-muted-foreground">{shopError}</div>
|
||||
}
|
||||
|
||||
if (serviceId && (!editingService || !scopedPlayerIdSet.has(editingService.playerId))) {
|
||||
return <div className="text-sm text-muted-foreground">服务不存在或当前身份不可编辑</div>
|
||||
}
|
||||
|
||||
@@ -12,12 +12,11 @@ import {
|
||||
TableRow,
|
||||
} from "@/components/ui/table"
|
||||
import { deletePlayerService, listPlayers, listServices } from "@/lib/api"
|
||||
import { resolveOwnerShop } from "@/lib/domain/resolve-current-shop"
|
||||
import { toApiError } from "@/lib/errors"
|
||||
import { useMyShop } from "@/lib/hooks/use-my-shop"
|
||||
import { notifyInfo, notifySuccess } from "@/lib/toast"
|
||||
import type { Player, PlayerService } from "@/lib/types"
|
||||
import { useAuthStore } from "@/store/auth"
|
||||
import { useShopStore } from "@/store/shops"
|
||||
import { Edit, Plus, Trash2 } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||
@@ -25,11 +24,14 @@ import { useCallback, useEffect, useMemo, useState } from "react"
|
||||
export default function ServicesPage() {
|
||||
const userId = useAuthStore((state) => state.user?.id)
|
||||
const currentRole = useAuthStore((state) => state.currentRole)
|
||||
const shops = useShopStore((state) => state.shops)
|
||||
const {
|
||||
shop: ownerShop,
|
||||
loading: shopLoading,
|
||||
error: shopError,
|
||||
} = useMyShop(currentRole === "owner")
|
||||
const [players, setPlayers] = useState<Player[]>([])
|
||||
const [services, setServices] = useState<PlayerService[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const ownerShop = resolveOwnerShop(userId, shops)
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
try {
|
||||
@@ -124,12 +126,18 @@ export default function ServicesPage() {
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{loading ? (
|
||||
{loading || (currentRole === "owner" && shopLoading) ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center text-sm text-muted-foreground">
|
||||
加载中...
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : currentRole === "owner" && shopError ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center text-sm text-muted-foreground">
|
||||
{shopError}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : scopedServices.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center text-sm text-muted-foreground">
|
||||
|
||||
@@ -5,12 +5,14 @@ import { toApiError } from "@/lib/errors"
|
||||
import type { Shop } from "@/lib/types"
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
|
||||
export function useMyShop() {
|
||||
export function useMyShop(enabled = true) {
|
||||
const [shop, setShop] = useState<Shop | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [loading, setLoading] = useState(enabled)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const refreshShop = useCallback(async () => {
|
||||
if (!enabled) return null
|
||||
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
@@ -29,12 +31,20 @@ export function useMyShop() {
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [])
|
||||
}, [enabled])
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) return
|
||||
|
||||
let cancelled = false
|
||||
|
||||
getMyShop()
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
if (cancelled) return undefined
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
return getMyShop()
|
||||
})
|
||||
.then((nextShop) => {
|
||||
if (cancelled) return
|
||||
setShop(nextShop ?? null)
|
||||
@@ -56,7 +66,7 @@ export function useMyShop() {
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [])
|
||||
}, [enabled])
|
||||
|
||||
return { shop, setShop, loading, error, refreshShop }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user