Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
45 lines
1.9 KiB
TypeScript
45 lines
1.9 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
|
|
import { cn } from '@/lib/cn'
|
|
|
|
export type SelectOptionItem = object
|
|
|
|
export function getOptionValue(item: SelectOptionItem, key: string): unknown {
|
|
return (item as Record<string, unknown>)[key]
|
|
}
|
|
|
|
export function buildOutsideLabel(label: ReactNode | undefined, labelIcon: ReactNode | null, required?: boolean, iconOffsetPx = 4) {
|
|
const hasLabelText = label !== undefined && label !== null && label !== ''
|
|
|
|
if (!hasLabelText && !labelIcon) return label
|
|
const iconOffsetClass = iconOffsetPx === 0 ? '' : iconOffsetPx === 2 ? 'translate-y-[2px]' : 'translate-y-[4px]'
|
|
|
|
return (
|
|
<span className={cn('inline-flex h-5 max-w-full flex-nowrap items-center gap-x-2 leading-5', labelIcon && iconOffsetClass)}>
|
|
{labelIcon ? <span className="inline-flex size-4 shrink-0 items-center justify-center">{labelIcon}</span> : null}
|
|
<span className="inline-flex min-w-0 flex-nowrap items-center gap-1 whitespace-nowrap leading-5">
|
|
{hasLabelText ? label : null}
|
|
{required ? <span className="shrink-0 text-fourth">*</span> : null}
|
|
</span>
|
|
</span>
|
|
)
|
|
}
|
|
|
|
export function unknownToDisplayString(value: unknown, fallback = ''): string {
|
|
if (value === null || value === undefined) return fallback
|
|
if (typeof value === 'string') return value
|
|
if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value)
|
|
|
|
return fallback
|
|
}
|
|
|
|
export function formatNumberInputDisplayValue(value: unknown, formatOptions?: Intl.NumberFormatOptions): string {
|
|
if (value === undefined || value === null || value === '') return ''
|
|
const number = typeof value === 'number' ? value : Number(value)
|
|
|
|
if (!Number.isFinite(number)) return unknownToDisplayString(value)
|
|
|
|
// Same Pinar baseline fix as formatNumber — U+066C sits high like an apostrophe.
|
|
return new Intl.NumberFormat('fa-IR', formatOptions).format(number).replaceAll('\u066C', ',')
|
|
}
|