import { apiFetch } from "@/app/lib/api-client"; import { avatarForName } from "@/app/data/avatars"; import { FALLBACK_PROFILES, PROFILE_GRADIENTS } from "./constants"; import type { DatingProfile, MatchIntent, ProfileRecord, SwipeResult } from "./types"; export function mapProfile(record: ProfileRecord, index: number): DatingProfile { const name = record.name || "数字游民"; const initial = name.slice(0, 1); return { id: record.id, name, age: Number(record.age || 26 + (index % 8)), location: record.location || "远程", citySlug: record.citySlug || "", gender: record.gender || "", single: record.single || "", tags: Array.isArray(record.tags) ? record.tags : ["数字游民", "远程工作者"], bio: record.bio || "正在完善个人资料,期待结识同城和同路的远程工作伙伴。", lookingFor: Array.isArray(record.lookingFor) ? record.lookingFor : ["friends", "explore"], gradient: PROFILE_GRADIENTS[index % PROFILE_GRADIENTS.length], initial, avatarColor: "bg-[#ff4d4f]", photo: record.photo || avatarForName(name), likedAt: record.likedAt, matchedAt: record.matchedAt, intent: record.intent, connectionId: record.connectionId, conversationId: record.conversationId, }; } export function filterFallbackProfiles( intent: MatchIntent, city: string, advanced?: { gender: string; single: string } ): DatingProfile[] { const cityQuery = city.trim().toLowerCase(); return FALLBACK_PROFILES.filter((profile) => { if (!profile.lookingFor.includes(intent)) return false; if (!cityQuery || cityQuery === "all") { // continue } else if ( profile.citySlug.toLowerCase() !== cityQuery && !profile.location.toLowerCase().includes(cityQuery) ) { return false; } if (advanced?.gender && advanced.gender !== "all" && profile.gender !== advanced.gender) { return false; } if (advanced?.single && advanced.single !== "all" && profile.single !== advanced.single) { return false; } return true; }); } export function formatTimeAgo(value?: string, locale = "zh"): string { if (!value) return locale === "zh" ? "刚刚活跃" : "Active now"; const date = new Date(value); if (Number.isNaN(date.getTime())) return locale === "zh" ? "刚刚活跃" : "Active now"; const diff = Date.now() - date.getTime(); const minutes = Math.floor(diff / 60000); if (minutes < 1) return locale === "zh" ? "刚刚" : "Just now"; if (minutes < 60) return locale === "zh" ? `${minutes} 分钟前` : `${minutes}m ago`; const hours = Math.floor(minutes / 60); if (hours < 24) return locale === "zh" ? `${hours} 小时前` : `${hours}h ago`; const days = Math.floor(hours / 24); if (days < 7) return locale === "zh" ? `${days} 天前` : `${days}d ago`; const weeks = Math.floor(days / 7); if (weeks < 5) return locale === "zh" ? `${weeks} 周前` : `${weeks}w ago`; const months = Math.floor(days / 30); return locale === "zh" ? `${Math.max(months, 1)} 月前` : `${Math.max(months, 1)}mo ago`; } export interface MatchQuota { vip: boolean; limit: number; used: number; remaining: number; } export async function fetchCandidates( intent: MatchIntent, city: string, advanced?: { gender: string; single: string } ): Promise { const params = new URLSearchParams({ intent }); if (city && city !== "all") params.set("city", city); if (advanced?.gender && advanced.gender !== "all") params.set("gender", advanced.gender); if (advanced?.single && advanced.single !== "all") params.set("single", advanced.single); params.set("exclude_swiped", "true"); const data = await apiFetch<{ items: ProfileRecord[] }>(`/api/matches/candidates?${params}`); return (data.items || []).map((item, index) => mapProfile(item, index)); } export async function fetchQuota(): Promise { const data = await apiFetch("/api/matches/quota"); return { vip: Boolean(data.vip), limit: Number(data.limit || 25), used: Number(data.used || 0), remaining: Number(data.remaining || 0), }; } export async function undoSwipe(): Promise<{ profileId?: string }> { return apiFetch<{ ok: boolean; profileId?: string }>("/api/matches/swipes/undo", { method: "POST", body: JSON.stringify({}), }); } export async function fetchLikes(): Promise { const data = await apiFetch<{ items: ProfileRecord[] }>("/api/matches/likes"); return (data.items || []).map((item, index) => mapProfile(item, index)); } export async function fetchMutualMatches(): Promise { const data = await apiFetch<{ items: ProfileRecord[] }>("/api/matches/mutual"); return (data.items || []).map((item, index) => mapProfile(item, index)); } export async function saveSwipe( profileId: string, action: "like" | "dislike", intent: MatchIntent ): Promise { return apiFetch("/api/matches/swipes", { method: "POST", body: JSON.stringify({ profileId, action, intent }), }); }