Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 1x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x | import i18n from '@/i18n';
export interface EventCategoryPresentation {
label: string;
emoji: string;
color: string;
tintColor: string;
textColor: string;
}
interface EventCategoryPresentationConfig {
emoji: string;
lightColor: string;
darkColor: string;
}
const CATEGORY_PRESENTATION_BY_NAME: Record<string, EventCategoryPresentationConfig> = {
sports: { emoji: '🏃', lightColor: '#2563EB', darkColor: '#60A5FA' },
music: { emoji: '🎵', lightColor: '#DB2777', darkColor: '#F472B6' },
education: { emoji: '🎓', lightColor: '#7C3AED', darkColor: '#A78BFA' },
technology: { emoji: '💻', lightColor: '#0891B2', darkColor: '#22D3EE' },
art: { emoji: '🎨', lightColor: '#EA580C', darkColor: '#FB923C' },
fooddrink: { emoji: '🍽️', lightColor: '#C2410C', darkColor: '#FDBA74' },
outdoors: { emoji: '🌲', lightColor: '#059669', darkColor: '#34D399' },
fitness: { emoji: '💪', lightColor: '#DC2626', darkColor: '#F87171' },
networking: { emoji: '🤝', lightColor: '#4F46E5', darkColor: '#818CF8' },
gaming: { emoji: '🎮', lightColor: '#9333EA', darkColor: '#C084FC' },
charity: { emoji: '💛', lightColor: '#B45309', darkColor: '#FBBF24' },
photography: { emoji: '📷', lightColor: '#0284C7', darkColor: '#38BDF8' },
travel: { emoji: '✈️', lightColor: '#0D9488', darkColor: '#2DD4BF' },
workshops: { emoji: '🛠️', lightColor: '#475569', darkColor: '#CBD5E1' },
conferences: { emoji: '🎤', lightColor: '#4338CA', darkColor: '#A5B4FC' },
moviescinema: { emoji: '🎬', lightColor: '#B91C1C', darkColor: '#FCA5A5' },
theatre: { emoji: '🎭', lightColor: '#C026D3', darkColor: '#E879F9' },
booksliterature: { emoji: '📚', lightColor: '#D97706', darkColor: '#FCD34D' },
wellness: { emoji: '🧘', lightColor: '#65A30D', darkColor: '#A3E635' },
volunteering: { emoji: '🙌', lightColor: '#BE123C', darkColor: '#FB7185' },
social: { emoji: '🤗', lightColor: '#0D9488', darkColor: '#5EEAD4' },
culture: { emoji: '🏛️', lightColor: '#7C2D12', darkColor: '#FDBA74' },
entertainment: { emoji: '🎉', lightColor: '#C026D3', darkColor: '#E879F9' },
};
const FALLBACK_CATEGORY_PRESENTATIONS: EventCategoryPresentationConfig[] = [
{ emoji: '📍', lightColor: '#2563EB', darkColor: '#60A5FA' },
{ emoji: '✨', lightColor: '#7C3AED', darkColor: '#A78BFA' },
{ emoji: '📌', lightColor: '#0D9488', darkColor: '#2DD4BF' },
{ emoji: '🎟️', lightColor: '#B45309', darkColor: '#FBBF24' },
];
const CATEGORY_TRANSLATION_KEYS_BY_NORMALIZED_NAME: Record<string, string> = {
sports: 'Sports',
music: 'Music',
education: 'Education',
technology: 'Technology',
art: 'Art',
fooddrink: 'Food & Drink',
outdoors: 'Outdoors',
fitness: 'Fitness',
networking: 'Networking',
gaming: 'Gaming',
charity: 'Charity',
photography: 'Photography',
travel: 'Travel',
workshops: 'Workshops',
conferences: 'Conferences',
moviescinema: 'Movies & Cinema',
theatre: 'Theatre',
booksliterature: 'Books & Literature',
wellness: 'Wellness',
volunteering: 'Volunteering',
};
function normalizeCategoryName(name: string): string {
return name.toLowerCase().replace(/[^a-z0-9]+/g, '');
}
function hashString(value: string): number {
return value.split('').reduce((hash, char) => {
return (hash * 31 + char.charCodeAt(0)) >>> 0;
}, 0);
}
function getReadableTextColor(backgroundColor: string): string {
const normalized = backgroundColor.replace('#', '');
const red = parseInt(normalized.slice(0, 2), 16);
const green = parseInt(normalized.slice(2, 4), 16);
const blue = parseInt(normalized.slice(4, 6), 16);
const luminance = (0.299 * red + 0.587 * green + 0.114 * blue) / 255;
return luminance > 0.62 ? '#0F172A' : '#FFFFFF';
}
export function getEventCategoryPresentation(
categoryName: string,
isDark: boolean,
): EventCategoryPresentation {
const rawLabel = categoryName.trim() || 'Event';
const normalizedName = normalizeCategoryName(rawLabel);
const translationLabelKey = CATEGORY_TRANSLATION_KEYS_BY_NORMALIZED_NAME[normalizedName] ?? rawLabel;
const translationKey = `events.categories.${translationLabelKey}`;
const translated = i18n.t(translationKey);
const label = translated === translationKey ? rawLabel : translated;
const config =
CATEGORY_PRESENTATION_BY_NAME[normalizedName] ??
FALLBACK_CATEGORY_PRESENTATIONS[
hashString(normalizedName) % FALLBACK_CATEGORY_PRESENTATIONS.length
];
const color = isDark ? config.darkColor : config.lightColor;
return {
label,
emoji: config.emoji,
color,
tintColor: `${color}${isDark ? '30' : '18'}`,
textColor: getReadableTextColor(color),
};
}
|