/** * 데이터 유틸리티 함수 * @description gameData, pageData 처리에 필요한 유틸리티 함수를 제공합니다. */ import type { PageDataValue, PageDataResourceContainer, PageDataTemplateComponents, PageDataResourceGroupType, } from '#layers/types/api/pageData' import type { OperateComponents } from '#layers/types/api/resourcesData' /** * 페이지 데이터를 기반으로 레이아웃 타입을 결정합니다. * @param pageData 페이지 데이터 * @returns 레이아웃 타입 ('default' | 'promotion') */ export const getLayoutType = ( pageData: PageDataValue | null ): 'default' | 'promotion' => { return pageData?.page_type === 2 ? 'promotion' : 'default' } /** * 이미지 타입인지 확인합니다. * @param type 리소스 그룹 타입 * @returns 이미지 타입 여부 */ export const isTypeImage = (type: PageDataResourceGroupType): boolean => { return ( type === 'IMG_COMM' || type === 'IMG_LANG' || type === 'IMG_COMM_GLOBAL' ) } /** * 비디오 타입인지 확인합니다. * @param type 리소스 그룹 타입 * @returns 비디오 타입 여부 */ export const isTypeVideo = (type: PageDataResourceGroupType): boolean => { return type === 'VID' } /** * 텍스트 타입인지 확인합니다. * @param type 리소스 그룹 타입 * @returns 텍스트 타입 여부 */ export const isTypeText = (type: PageDataResourceGroupType): boolean => { return type === 'TXT' } /** * 버튼 타입인지 확인합니다. * @param type 리소스 그룹 타입 * @returns 버튼 타입 여부 */ export const isTypeButton = (type: PageDataResourceGroupType): boolean => { return type === 'BTN' } /** * 컴포넌트 그룹에 데이터가 존재하는지 확인합니다. * @param components props.components 또는 group 객체 * @param componentName 컴포넌트 이름 * @returns 데이터 존재 여부 */ export const hasComponentGroup = ( components: PageDataTemplateComponents, componentName: string ): boolean => { if (!components) return false const component = components[componentName] as PageDataResourceContainer return component?.groups && component.groups.length > 0 } /** * 컴포넌트 컨테이너를 반환합니다. * @param components props.components * @param componentName 컴포넌트 이름 * @param options 옵션 * - hasGroup: groups 속성에서 데이터 가져오기 (기본값: false) * - maxLength: 최대 길이 제한 * - minLength: 최소 길이 보장 (데이터 반복) * @returns 컴포넌트 컨테이너 배열 */ export const getComponentContainer = ( components: PageDataTemplateComponents | OperateComponents, componentName: string, options: { hasGroup?: boolean; maxLength?: number; minLength?: number } = {} ) => { if (!components) return [] const { hasGroup = false, maxLength, minLength } = options // 1. 초기 컨테이너 가져오기 const component = components[componentName] if (!component) return [] let result = hasGroup && 'groups' in component ? component.groups : component // 2. 최소 길이 보장 (데이터 복제) if (minLength && result.length > 1 && result.length < minLength) { const repeatTimes = Math.ceil(minLength / result.length) result = Array(repeatTimes).fill(result).flat() } // 3. 최대 길이 제한 if (maxLength && result.length > maxLength) { return result.slice(0, maxLength) } return result } /** * 컴포넌트 그룹의 첫 번째 데이터를 반환합니다. * @param components props.components 또는 group 객체 * @param componentName 컴포넌트 이름 * @returns 첫 번째 그룹 데이터 또는 null */ export const getComponentGroup = ( components: PageDataTemplateComponents | OperateComponents, componentName: string ) => { if (!components) return null return components[componentName]?.groups?.[0] || null } /** * 컴포넌트 그룹의 모든 데이터를 반환합니다. * @param components props.components 또는 group 객체 * @param componentName 컴포넌트 이름 * @returns 그룹 배열 데이터 */ export const getComponentGroupAry = ( components: PageDataTemplateComponents | OperateComponents, componentName: string ) => { if (!components) return [] return components[componentName]?.groups || [] } /** * 현재 시간의 타임스탬프를 반환합니다. * @param unit 단위 ('ms' | 's') - 밀리초 또는 초 * @returns 타임스탬프 */ export const getCurrentTimestamp = (unit: 'ms' | 's' = 'ms'): number => { const now = Date.now() return unit === 's' ? Math.floor(now / 1000) : now } export const formatDateOffset = ({ ts, lang, useSeconds, useTimezone }: { ts: number lang: string useSeconds?: boolean useTimezone?: boolean }) => { const offset = { ko: 9, ja: 9, 'zh-tw': 8, en: 0 }[lang] || 0 const date = new Date(ts + offset * 3600000) const pad = (n: number) => String(n).padStart(2, '0') const year = date.getUTCFullYear() const month = date.getUTCMonth() + 1 const day = date.getUTCDate() const hours = date.getUTCHours() const minutes = date.getUTCMinutes() const seconds = date.getUTCSeconds() if (lang === 'ko') { let format = `${year}-${pad(month)}-${pad(day)} ${pad(hours)}:${pad(minutes)}` format += useSeconds ? `:${pad(seconds)}` : '' format += useTimezone ? ' (KST)' : '' return `${format}` } else if (lang === 'zh-tw') { let format = `${year}-${pad(month)}-${pad(day)} ${pad(hours)}:${pad(minutes)}` format += useSeconds ? `:${pad(seconds)}` : '' format += useTimezone ? ` (UTC${offset > 0 ? '+' + offset : ''})` : '' return `${format}` } else if (lang === 'ja') { let format = `${year}-${pad(month)}-${pad(day)} ${pad(hours)}:${pad(minutes)}` format += useSeconds ? `:${pad(seconds)}` : '' format += useTimezone ? ' (日本時間)' : '' return `${format}` } else { //= en let format = `${pad(month)}/${pad(day)}/${year} ${pad(hours)}:${pad(minutes)}` format += useSeconds ? `:${pad(seconds)}` : '' format += useTimezone ? ' (UTC)' : '' return `${format}` } }