Files
Spanglish/frontend/src/lib/socialLinks.tsx
2026-01-31 22:32:54 +00:00

208 lines
8.9 KiB
TypeScript

// Social links configuration - reads from environment variables
// All links are optional - if not set, they won't be displayed
export interface SocialLinks {
whatsapp?: string;
instagram?: string;
email?: string;
telegram?: string;
tiktok?: string;
}
export interface SocialLink {
type: 'whatsapp' | 'instagram' | 'email' | 'telegram' | 'tiktok';
url: string;
label: string;
handle?: string;
}
// Get raw values from env
export const socialConfig: SocialLinks = {
whatsapp: process.env.NEXT_PUBLIC_WHATSAPP || undefined,
instagram: process.env.NEXT_PUBLIC_INSTAGRAM || undefined,
email: process.env.NEXT_PUBLIC_EMAIL || undefined,
telegram: process.env.NEXT_PUBLIC_TELEGRAM || undefined,
tiktok: process.env.NEXT_PUBLIC_TIKTOK || undefined,
};
// Generate URLs from handles/values
export function getWhatsAppUrl(value?: string): string | null {
if (!value) return null;
// If it's already a full URL (group invite link or wa.me link), return as-is
if (value.startsWith('https://') || value.startsWith('http://')) {
return value;
}
// Otherwise, treat as phone number - remove any non-digit characters except +
const clean = value.replace(/[^\d+]/g, '');
return `https://wa.me/${clean.replace('+', '')}`;
}
export function getInstagramUrl(value?: string): string | null {
if (!value) return null;
// If it's already a full URL, return as-is
if (value.startsWith('https://') || value.startsWith('http://')) {
return value;
}
// Otherwise, treat as handle - remove @ if present
const clean = value.replace('@', '');
return `https://instagram.com/${clean}`;
}
export function getEmailUrl(email?: string): string | null {
if (!email) return null;
return `mailto:${email}`;
}
export function getTelegramUrl(value?: string): string | null {
if (!value) return null;
// If it's already a full URL, return as-is
if (value.startsWith('https://') || value.startsWith('http://')) {
return value;
}
// Otherwise, treat as handle - remove @ if present
const clean = value.replace('@', '');
return `https://t.me/${clean}`;
}
export function getTikTokUrl(value?: string): string | null {
if (!value) return null;
// If it's already a full URL, return as-is
if (value.startsWith('https://') || value.startsWith('http://')) {
return value;
}
// Otherwise, treat as handle - add @ if not present
const clean = value.startsWith('@') ? value : `@${value}`;
return `https://www.tiktok.com/${clean}`;
}
// Extract display handle from URL or value
function extractInstagramHandle(value: string): string {
// If it's a URL, extract the username from the path
if (value.startsWith('http')) {
const match = value.match(/instagram\.com\/([^/?]+)/);
return match ? `@${match[1]}` : '@instagram';
}
// Otherwise it's already a handle
return `@${value.replace('@', '')}`;
}
function extractTelegramHandle(value: string): string {
// If it's a URL, extract the channel/username from the path
if (value.startsWith('http')) {
const match = value.match(/t\.me\/([^/?]+)/);
return match ? `@${match[1]}` : '@telegram';
}
// Otherwise it's already a handle
return `@${value.replace('@', '')}`;
}
function extractTikTokHandle(value: string): string {
// If it's a URL, extract the username from the path
if (value.startsWith('http')) {
const match = value.match(/tiktok\.com\/(@?[^/?]+)/);
if (match) {
const handle = match[1];
return handle.startsWith('@') ? handle : `@${handle}`;
}
return '@tiktok';
}
// Otherwise it's already a handle
return value.startsWith('@') ? value : `@${value}`;
}
// Get all active social links as an array
export function getSocialLinks(): SocialLink[] {
const links: SocialLink[] = [];
if (socialConfig.whatsapp) {
const url = getWhatsAppUrl(socialConfig.whatsapp);
if (url) {
links.push({
type: 'whatsapp',
url,
label: 'WhatsApp',
handle: '@WhatsApp community',
});
}
}
if (socialConfig.instagram) {
const url = getInstagramUrl(socialConfig.instagram);
if (url) {
links.push({
type: 'instagram',
url,
label: 'Instagram',
handle: extractInstagramHandle(socialConfig.instagram),
});
}
}
if (socialConfig.email) {
const url = getEmailUrl(socialConfig.email);
if (url) {
links.push({
type: 'email',
url,
label: 'Email',
handle: socialConfig.email,
});
}
}
if (socialConfig.telegram) {
const url = getTelegramUrl(socialConfig.telegram);
if (url) {
links.push({
type: 'telegram',
url,
label: 'Telegram',
handle: extractTelegramHandle(socialConfig.telegram),
});
}
}
if (socialConfig.tiktok) {
const url = getTikTokUrl(socialConfig.tiktok);
if (url) {
links.push({
type: 'tiktok',
url,
label: 'TikTok',
handle: extractTikTokHandle(socialConfig.tiktok),
});
}
}
return links;
}
// SVG icons for each platform
export const socialIcons = {
whatsapp: (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
</svg>
),
instagram: (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
</svg>
),
email: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" />
</svg>
),
telegram: (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/>
</svg>
),
tiktok: (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M19.59 6.69a4.83 4.83 0 0 1-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 0 1-5.2 1.74 2.89 2.89 0 0 1 2.31-4.64 2.93 2.93 0 0 1 .88.13V9.4a6.84 6.84 0 0 0-1-.05A6.33 6.33 0 0 0 5 20.1a6.34 6.34 0 0 0 10.86-4.43v-7a8.16 8.16 0 0 0 4.77 1.52v-3.4a4.85 4.85 0 0 1-1-.1z"/>
</svg>
),
};