expo-popcore-old/utils/profile-data.ts

74 lines
1.9 KiB
TypeScript

import type { ImageSourcePropType } from 'react-native';
export type IdentityStat = {
key: string;
label: string;
value: number;
};
const STAT_BLUEPRINT: IdentityStat[] = [
{ key: 'likes', label: 'likes', value: 0 },
{ key: 'posts', label: 'posts', value: 0 },
{ key: 'views', label: 'views', value: 0 },
];
export function createStats(user: unknown): IdentityStat[] {
const source = (user as Record<string, unknown>) ?? {};
return STAT_BLUEPRINT.map(stat => ({
...stat,
value: deriveNumericValue(source[stat.key]),
}));
}
export function deriveDisplayName(user: unknown): string | null {
if (!user || typeof user !== 'object') {
return null;
}
const data = user as Record<string, unknown>;
return ensureString(data.username) ?? ensureString(data.name) ?? null;
}
export function deriveAvatarSource(user: unknown): ImageSourcePropType | undefined {
if (!user || typeof user !== 'object') {
return undefined;
}
const image = ensureString((user as Record<string, unknown>).image);
if (!image) {
return undefined;
}
return { uri: image };
}
export function deriveNumericValue(value: unknown): number {
if (typeof value === 'number' && Number.isFinite(value)) {
return value;
}
if (typeof value === 'string') {
const parsed = Number(value);
if (Number.isFinite(parsed)) {
return parsed;
}
}
return 0;
}
export function deriveInitials(name: string): string {
const tokens = name
.replace(/[_-]+/g, ' ')
.split(/\s+/)
.filter(Boolean);
if (tokens.length === 0) {
return 'AI';
}
const initials = tokens.slice(0, 2).map(part => part[0]?.toUpperCase() ?? '');
return initials.join('') || tokens[0][0]?.toUpperCase() || 'AI';
}
function ensureString(value: unknown): string | null {
if (typeof value !== 'string') {
return null;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}