import { createContext, useContext } from 'react' import { translateUIMessage } from '@/lib/i18n' import { apiGet } from '@/lib/api' import type { LocaleCode } from '@/lib/locales' import type { CountField, CountsResource } from '@/lib/counts' export type CountsAxis = { field: string; grain?: string } export type CountsCondition = { field: string; operator: string; value?: string; end?: string; blank?: boolean } export type CountsFieldType = 'string' | 'integer' | 'datetime' | 'enum' | 'json' | 'boolean' export const countsResources: CountsResource[] = [ 'posts', 'tags', 'nico_tags', 'tag_descriptions', 'tag_groups', 'materials'] export type CountsFieldMetadata = { key: string; type: CountsFieldType; nullable: boolean; operators: string[] } export type CountsDefinition = { fields: CountsFieldMetadata[] axes: { latest: string[]; history: string[] } grains: string[] } export const CountsDefinitionContext = createContext (null) export const useCountsDefinition = (): CountsDefinition => { const definition = useContext (CountsDefinitionContext) if (definition == null) throw new Error ('Missing Counts definition') return definition } export const fetchCountsDefinition = (resource: CountsResource): Promise => apiGet (`/counts/definitions/${encodeURIComponent (resource)}`) export const countsFilterFields = ( definition: CountsDefinition, ): Record => Object.fromEntries ( definition.fields.map (field => [field.key, field.type])) export const countsFieldLabel = (key: string): string => { const labels: Record = { resource_id: 'columns.resourceId', version_no: 'history:version', user: 'history:actor', created_at: 'columns.changedAt', name: 'history:name', title: 'columns.postTitle', url: 'columns.postURL', thumbnail_base: 'columns.thumbnailURL', tags: 'columns.tags', tags_json: 'columns.tags', names: 'columns.names', aliases: 'tags:aliases', category: 'common:categoryLabel', language_code: 'columns.language', source_language_code: 'attributes.sourceLanguage', changed_field: 'changedField' } return labels[key] ?? `attributes.${key}` } export const countsEventTypes = ['create', 'update', 'discard', 'restore'] as const export const countsAxisLabel = ( axis: CountsAxis, definition: CountsDefinition, locale: LocaleCode, ): { text: string; language: string } => { const field = translateUIMessage (countsFieldLabel (axis.field), 'counts', locale) if (axis.grain == null || definition.fields.find (item => item.key === axis.field) ?.type !== 'datetime') return field return translateUIMessage ('axisWithGrain', 'counts', locale, { field: field.text, grain: translateUIMessage (`grains.${axis.grain}`, 'counts', locale).text }) } export const countsAxisFields = ( definition: CountsDefinition, history: boolean, ): CountField[] => definition.axes[history ? 'history' : 'latest'] .map (key => ({ key, label: countsFieldLabel (key) })) export const readCountsJSON = (params: URLSearchParams, key: string, fallback: T): T => { try { return JSON.parse (params.get (key) ?? JSON.stringify (fallback)) as T } catch { return fallback } }