Implement package limit notification system
This commit is contained in:
@@ -5,7 +5,7 @@ import BottomNav from '../components/BottomNav';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { uploadPhoto } from '../services/photosApi';
|
||||
import { uploadPhoto, type UploadError } from '../services/photosApi';
|
||||
import { useGuestTaskProgress } from '../hooks/useGuestTaskProgress';
|
||||
import { cn } from '@/lib/utils';
|
||||
import {
|
||||
@@ -117,6 +117,7 @@ export default function UploadPage() {
|
||||
const [reviewPhoto, setReviewPhoto] = useState<{ dataUrl: string; file: File } | null>(null);
|
||||
const [uploadProgress, setUploadProgress] = useState(0);
|
||||
const [uploadError, setUploadError] = useState<string | null>(null);
|
||||
const [uploadWarning, setUploadWarning] = useState<string | null>(null);
|
||||
|
||||
const [eventPackage, setEventPackage] = useState<EventPackage | null>(null);
|
||||
const [canUpload, setCanUpload] = useState(true);
|
||||
@@ -262,10 +263,29 @@ export default function UploadPage() {
|
||||
setCanUpload(true);
|
||||
setUploadError(null);
|
||||
}
|
||||
|
||||
if (pkg?.package?.max_photos) {
|
||||
const max = Number(pkg.package.max_photos);
|
||||
const used = Number(pkg.used_photos ?? 0);
|
||||
const ratio = max > 0 ? used / max : 0;
|
||||
if (ratio >= 0.8 && ratio < 1) {
|
||||
const remaining = Math.max(0, max - used);
|
||||
setUploadWarning(
|
||||
t('upload.limitWarning')
|
||||
.replace('{remaining}', `${remaining}`)
|
||||
.replace('{max}', `${max}`)
|
||||
);
|
||||
} else {
|
||||
setUploadWarning(null);
|
||||
}
|
||||
} else {
|
||||
setUploadWarning(null);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to check package limits', err);
|
||||
setCanUpload(false);
|
||||
setUploadError(t('upload.limitCheckError'));
|
||||
setUploadWarning(null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -520,7 +540,42 @@ export default function UploadPage() {
|
||||
navigateAfterUpload(photoId);
|
||||
} catch (error: unknown) {
|
||||
console.error('Upload failed', error);
|
||||
setUploadError(getErrorMessage(error) || t('upload.status.failed'));
|
||||
const uploadErr = error as UploadError;
|
||||
setUploadWarning(null);
|
||||
const meta = uploadErr.meta as Record<string, unknown> | undefined;
|
||||
switch (uploadErr.code) {
|
||||
case 'photo_limit_exceeded': {
|
||||
if (meta && typeof meta.used === 'number' && typeof meta.limit === 'number') {
|
||||
const limitText = t('upload.limitReached')
|
||||
.replace('{used}', `${meta.used}`)
|
||||
.replace('{max}', `${meta.limit}`);
|
||||
setUploadError(limitText);
|
||||
} else {
|
||||
setUploadError(t('upload.errors.photoLimit'));
|
||||
}
|
||||
setCanUpload(false);
|
||||
break;
|
||||
}
|
||||
case 'upload_device_limit': {
|
||||
setUploadError(t('upload.errors.deviceLimit'));
|
||||
setCanUpload(false);
|
||||
break;
|
||||
}
|
||||
case 'event_package_missing':
|
||||
case 'event_not_found': {
|
||||
setUploadError(t('upload.errors.packageMissing'));
|
||||
setCanUpload(false);
|
||||
break;
|
||||
}
|
||||
case 'gallery_expired': {
|
||||
setUploadError(t('upload.errors.galleryExpired'));
|
||||
setCanUpload(false);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
setUploadError(getErrorMessage(uploadErr) || t('upload.errors.generic'));
|
||||
}
|
||||
}
|
||||
setMode('review');
|
||||
} finally {
|
||||
if (uploadProgressTimerRef.current) {
|
||||
@@ -773,6 +828,13 @@ export default function UploadPage() {
|
||||
</div>
|
||||
|
||||
<div className="relative z-30 flex flex-col gap-3 bg-gradient-to-t from-black via-black/80 to-transparent p-4">
|
||||
{uploadWarning && (
|
||||
<Alert className="border-yellow-400/20 bg-yellow-500/10 text-white">
|
||||
<AlertDescription className="text-xs">
|
||||
{uploadWarning}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
{uploadError && (
|
||||
<Alert variant="destructive" className="bg-red-500/10 text-white">
|
||||
<AlertDescription className="flex items-center gap-2 text-xs">
|
||||
|
||||
Reference in New Issue
Block a user