|
1 | | -import { TableCellValue, TableFormView } from 'mobx-lark'; |
| 1 | +import { TableCellUser, TableCellValue, TableFormView } from 'mobx-lark'; |
2 | 2 | import { formatDate } from 'web-utility'; |
3 | 3 |
|
4 | 4 | import type { HackathonScheduleTone } from './Schedule'; |
@@ -33,11 +33,72 @@ export const buildAgendaTypeLabelMap = ({ |
33 | 33 | export const isPublicForm = ({ shared_limit }: TableFormView) => |
34 | 34 | ['anyone_editable'].includes(shared_limit as string); |
35 | 35 |
|
| 36 | +type NamedLike = { name?: string | null }; |
| 37 | +type TextLike = TableCellValue | NamedLike | null | undefined; |
| 38 | +type TextListLike = TextLike | TextLike[]; |
| 39 | + |
| 40 | +const textOf = (value: TextLike) => { |
| 41 | + if (!value) return ''; |
| 42 | + |
| 43 | + if (typeof value === 'object' && !Array.isArray(value)) |
| 44 | + return 'name' in value ? (value.name || '').trim() : ''; |
| 45 | + |
| 46 | + const text = value.toString().trim(); |
| 47 | + |
| 48 | + return text === '[object Object]' ? '' : text; |
| 49 | +}; |
| 50 | + |
| 51 | +export const firstTextOf = (value: TextListLike) => |
| 52 | + (Array.isArray(value) ? value.map(textOf).find(Boolean) : textOf(value)) || ''; |
| 53 | + |
| 54 | +export const textListOf = (value: TextListLike) => |
| 55 | + (Array.isArray(value) ? value : [value]).map(textOf).filter(Boolean); |
| 56 | + |
| 57 | +export const relationNameOf = (value: TextListLike) => firstTextOf(value); |
| 58 | + |
| 59 | +export const userOf = (value?: TableCellValue | TableCellUser) => |
| 60 | + value && typeof value === 'object' && !Array.isArray(value) && 'name' in value |
| 61 | + ? (value as TableCellUser) |
| 62 | + : undefined; |
| 63 | + |
36 | 64 | export const formatMoment = (value?: TableCellValue) => (value ? formatDate(value as string) : ''); |
37 | 65 |
|
38 | 66 | export const formatPeriod = (startedAt?: TableCellValue, endedAt?: TableCellValue) => |
39 | 67 | [formatMoment(startedAt), formatMoment(endedAt)].filter(Boolean).join(' - '); |
40 | 68 |
|
| 69 | +export const timeOf = (value?: TableCellValue) => { |
| 70 | + const time = new Date((value as string) || 0).getTime(); |
| 71 | + |
| 72 | + return Number.isFinite(time) ? time : NaN; |
| 73 | +}; |
| 74 | + |
| 75 | +export interface CountdownWindow { |
| 76 | + startedAt?: TableCellValue; |
| 77 | + endedAt?: TableCellValue; |
| 78 | +} |
| 79 | + |
| 80 | +export const resolveCountdownState = <T extends CountdownWindow>( |
| 81 | + items: T[], |
| 82 | + now: number, |
| 83 | + startTime?: TableCellValue, |
| 84 | + endTime?: TableCellValue, |
| 85 | +) => { |
| 86 | + const nextItem = items.find(({ startedAt, endedAt }) => { |
| 87 | + const started = timeOf(startedAt); |
| 88 | + const ended = timeOf(endedAt); |
| 89 | + |
| 90 | + return Number.isFinite(started) && Number.isFinite(ended) && now <= ended; |
| 91 | + }); |
| 92 | + const nextStartedAt = timeOf(nextItem?.startedAt); |
| 93 | + const countdownTo = |
| 94 | + (Number.isFinite(nextStartedAt) && nextStartedAt > now |
| 95 | + ? (nextItem?.startedAt as string | undefined) |
| 96 | + : (nextItem?.endedAt as string | undefined)) || |
| 97 | + (timeOf(startTime) > now ? (startTime as string | undefined) : (endTime as string | undefined)); |
| 98 | + |
| 99 | + return { nextItem, countdownTo }; |
| 100 | +}; |
| 101 | + |
41 | 102 | export const previewText = (items: TableCellValue[], fallback: string) => |
42 | 103 | items |
43 | 104 | .map(item => item?.toString()) |
@@ -95,8 +156,8 @@ export const dateKeyOf = (value?: TableCellValue) => { |
95 | 156 | export const compactDateKeyOf = (value?: TableCellValue) => dateKeyOf(value).replace('-', '.'); |
96 | 157 |
|
97 | 158 | export const daysBetween = (startedAt?: TableCellValue, endedAt?: TableCellValue) => { |
98 | | - const start = new Date((startedAt as string) || '').getTime(); |
99 | | - const end = new Date((endedAt as string) || '').getTime(); |
| 159 | + const start = timeOf(startedAt); |
| 160 | + const end = timeOf(endedAt); |
100 | 161 |
|
101 | 162 | if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) return 0; |
102 | 163 |
|
|
0 commit comments