Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
55 lines
1.9 KiB
TypeScript
55 lines
1.9 KiB
TypeScript
/**
|
|
* presentEventCapacityBadge — label + tone for browse/discovery capacity chips.
|
|
*
|
|
* Purpose
|
|
* - Shared remaining-capacity / ended / full presentation for medium cards.
|
|
* - Separate from host progress UI (`presentHostCapacity`).
|
|
*/
|
|
|
|
import type { EventCapacityTone } from '@/features/events/eventCapacity'
|
|
import { capacityToneFromRemaining, isOccupancyFull, remainingSeatCount } from '@/features/events/eventCapacity'
|
|
import { isEventEnded } from '@/features/events/eventEditPolicy'
|
|
import { formatNumber } from '@/helpers'
|
|
import { format, texts } from '@/texts'
|
|
|
|
export interface PresentEventCapacityBadgeInput {
|
|
capacity: number
|
|
bookedCount: number
|
|
reservedCapacity?: number
|
|
status?: string
|
|
endsAt?: string
|
|
}
|
|
|
|
export interface PresentEventCapacityBadgeResult {
|
|
label: string
|
|
tone: EventCapacityTone
|
|
}
|
|
|
|
const formatRemainingCapacity = (remaining: number) => {
|
|
if (remaining <= 0) return texts.discovery.capacityFull
|
|
|
|
return format(texts.events.remainingCapacity, { count: formatNumber(remaining) })
|
|
}
|
|
|
|
export function presentEventCapacityBadge(input: PresentEventCapacityBadgeInput): PresentEventCapacityBadgeResult {
|
|
const reserved = input.reservedCapacity ?? 0
|
|
const remaining = remainingSeatCount(input.capacity, input.bookedCount, reserved)
|
|
const isFull = isOccupancyFull(input.capacity, input.bookedCount, reserved) || input.status === 'full'
|
|
|
|
// لغو/رد با «اتمام رویداد» فرق دارد؛ بج ظرفیت برای این وضعیتها معنا ندارد.
|
|
if (input.status === 'cancelled' || input.status === 'rejected') {
|
|
return { label: '', tone: 'neutral' }
|
|
}
|
|
|
|
const isEnded = input.status != null && input.endsAt != null ? isEventEnded(input.status, input.endsAt) : false
|
|
|
|
if (isEnded) {
|
|
return { label: texts.events.eventEnded, tone: 'danger' }
|
|
}
|
|
|
|
return {
|
|
label: formatRemainingCapacity(remaining),
|
|
tone: isFull ? 'danger' : capacityToneFromRemaining(remaining, input.capacity),
|
|
}
|
|
}
|