admin
Some checks are pending
Deploy Admin Panel / Deploy Admin Panel (push) Waiting to run
Deploy Admin Panel / Admin Panel Verification (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions

This commit is contained in:
Dmitry 2025-12-14 22:49:40 +03:00
parent b86e840cc6
commit 0cfd5f4524
3 changed files with 98 additions and 55 deletions

View file

@ -52,8 +52,20 @@ export function BulkCardEditor({ images, onComplete, onCancel }: BulkCardEditorP
packsApi
.getPacks({ page: 1, limit: 100, search: '' })
.then((response) => {
if (response && response.items) {
setPacksData(response.items.map((pack) => ({ id: pack.id, title: pack.title })))
try {
if (response && response.items && Array.isArray(response.items)) {
const packs = response.items.map((pack: any) => ({
id: String(pack.id || ''),
title: String(pack.title || pack.id || '')
}))
setPacksData(packs)
} else {
console.warn('Unexpected packs response format:', response)
setPacksData([])
}
} catch (error) {
console.error('Error processing packs response:', error)
setPacksData([])
}
})
.catch((error) => {
@ -66,6 +78,7 @@ export function BulkCardEditor({ images, onComplete, onCancel }: BulkCardEditorP
// Initialize cards data
useEffect(() => {
if (images.length > 0) {
const initialData = new Map<string, CardData>()
images.forEach((image) => {
initialData.set(image.id, {
@ -82,15 +95,17 @@ export function BulkCardEditor({ images, onComplete, onCancel }: BulkCardEditorP
})
})
setCardsData(initialData)
}
}, [images])
const currentImage = images[currentIndex]
const currentCard = cardsData.get(currentImage?.id || '')
const currentCard = currentImage ? cardsData.get(currentImage.id) : undefined
const updateMutation = useMutation({
mutationFn: (card: GameCardDto) => cardsApi.upsertCard(card),
onSuccess: (response) => {
queryClient.invalidateQueries({ queryKey: ['cards'] })
if (currentImage) {
const imageId = currentImage.id
setCardsData((prev) => {
const newData = new Map(prev)
@ -104,6 +119,7 @@ export function BulkCardEditor({ images, onComplete, onCancel }: BulkCardEditorP
}
return newData
})
}
toast.success('Card saved successfully')
},
onError: (error: unknown) => {
@ -113,7 +129,7 @@ export function BulkCardEditor({ images, onComplete, onCancel }: BulkCardEditorP
})
const handleFieldChange = (field: keyof CardData, value: string) => {
if (!currentCard) return
if (!currentCard || !currentImage) return
setCardsData((prev) => {
const newData = new Map(prev)
@ -170,8 +186,21 @@ export function BulkCardEditor({ images, onComplete, onCancel }: BulkCardEditorP
const savedCount = Array.from(cardsData.values()).filter((card) => card.isSaved).length
const totalCount = images.length
// Wait for images and cards data to be initialized
if (images.length === 0) {
return (
<div className="p-4">
<p className="text-muted-foreground">No images uploaded</p>
</div>
)
}
if (!currentImage || !currentCard) {
return <div>Loading...</div>
return (
<div className="p-4">
<p className="text-muted-foreground">Initializing card data...</p>
</div>
)
}
return (
@ -199,15 +228,25 @@ export function BulkCardEditor({ images, onComplete, onCancel }: BulkCardEditorP
<Card>
<CardHeader>
<CardTitle>Image Preview</CardTitle>
<CardDescription>{currentImage.file.name}</CardDescription>
<CardDescription>{currentImage.file?.name || 'Unknown'}</CardDescription>
</CardHeader>
<CardContent>
<div className="relative aspect-square border rounded-lg overflow-hidden bg-muted">
{currentImage.preview ? (
<img
src={currentImage.preview}
alt={currentImage.file.name}
alt={currentImage.file?.name || 'Card image'}
className="w-full h-full object-contain"
onError={(e) => {
console.error('Failed to load image:', currentImage.preview)
e.currentTarget.style.display = 'none'
}}
/>
) : (
<div className="w-full h-full flex items-center justify-center text-muted-foreground">
Image preview not available
</div>
)}
</div>
</CardContent>
</Card>
@ -222,19 +261,21 @@ export function BulkCardEditor({ images, onComplete, onCancel }: BulkCardEditorP
<div className="space-y-2">
<Label htmlFor="packId">Pack ID (optional)</Label>
<Select
value={currentCard.packId}
onValueChange={(value: string) => handleFieldChange('packId', value)}
value={currentCard.packId || undefined}
onValueChange={(value: string) => handleFieldChange('packId', value || '')}
>
<SelectTrigger>
<SelectValue placeholder="Select a pack (optional)" />
</SelectTrigger>
<SelectContent>
<SelectItem value="">None</SelectItem>
{packsData.map((pack) => (
{packsData && packsData.length > 0 ? (
packsData.map((pack) => (
<SelectItem key={pack.id} value={pack.id}>
{pack.title}
{pack.title || pack.id}
</SelectItem>
))}
))
) : null}
</SelectContent>
</Select>
</div>

View file

@ -366,19 +366,21 @@ export default function CardsPage() {
<div className="space-y-2">
<Label htmlFor="packId">Pack ID (optional)</Label>
<Select
value={formData.packId}
onValueChange={(value: string) => setFormData(prev => ({ ...prev, packId: value }))}
value={formData.packId || undefined}
onValueChange={(value: string) => setFormData(prev => ({ ...prev, packId: value || '' }))}
>
<SelectTrigger>
<SelectValue placeholder="Select a pack (optional)" />
</SelectTrigger>
<SelectContent>
<SelectItem value="">None</SelectItem>
{packsData?.items.map((pack) => (
{packsData?.items && packsData.items.length > 0 ? (
packsData.items.map((pack) => (
<SelectItem key={pack.id} value={pack.id}>
{pack.title}
{pack.title || pack.id}
</SelectItem>
))}
))
) : null}
</SelectContent>
</Select>
</div>

View file

@ -387,10 +387,10 @@ export default function UsersPage() {
<div className="space-y-2">
<Label>Packs Owned</Label>
<div className="border rounded-lg max-h-[200px] overflow-y-auto p-2">
{packsData?.items.length === 0 ? (
{!packsData?.items || packsData.items.length === 0 ? (
<div className="text-sm text-muted-foreground">No packs available</div>
) : (
packsData?.items.map((pack) => (
packsData.items.map((pack) => (
<div key={pack.id} className="flex items-center space-x-2 py-1">
<Checkbox
id={`pack-${pack.id}`}