import { DeliveryTruck01Icon, Mail01Icon, Message01Icon, PackageIcon, } from "@hugeicons/core-free-icons" import type { QueryFunctionContext } from "@tanstack/react-query" import type { Notification } from "@workspace/blocks/notifications" const RANDOM_USER_API_URL = "https://randomuser.me/api/1.4/?results=4&inc=name,email,picture&nat=au,ca,de,fr,gb,nl,nz,us&noinfo" interface RandomUser { email: string name: { first: string last: string } picture: { medium: string } } const HOUR_IN_MILLISECONDS = 60 * 60 * 1000 function getCreatedAt(hoursAgo: number) { return new Date(Date.now() - hoursAgo * HOUR_IN_MILLISECONDS).toISOString() } export const fallbackNotifications: readonly Notification[] = [ { id: "friend-request-deja-brady", title: "Deja Brady sent you a friend request", createdAt: getCreatedAt(11), category: "Communication", isRead: false, media: { kind: "avatar", src: "https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/images/mock/avatar/avatar-2.webp", alt: "Deja Brady", }, actions: [ { id: "accept", label: "Accept" }, { id: "decline", label: "Decline", intent: "neutral" }, ], }, { id: "mention-minimal-ui", title: "Jayvon Hull mentioned you in Minimal UI", createdAt: getCreatedAt(24), category: "Project UI", to: "/workspace/tasks", isRead: false, media: { kind: "avatar", src: "https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/images/mock/avatar/avatar-3.webp", alt: "Jayvon Hull", }, actions: [{ id: "view", label: "View", intent: "neutral" }], }, { id: "order-placed", title: "Your order is placed", description: "The order is confirmed and waiting for shipping.", createdAt: getCreatedAt(24 * 6), category: "Order", isRead: true, media: { kind: "icon", icon: PackageIcon, tone: "warning", }, }, { id: "order-shipping", title: "Delivery in progress", description: "Your order has left the warehouse and is being shipped.", createdAt: getCreatedAt(24 * 7), category: "Order", isRead: true, media: { kind: "icon", icon: DeliveryTruck01Icon, tone: "success", }, }, { id: "unread-messages", title: "You have 5 unread messages", createdAt: getCreatedAt(24 * 8), category: "Communication", to: "/workspace/tasks", isRead: true, media: { kind: "icon", icon: Message01Icon, tone: "info", }, }, { id: "new-mail", title: "You have new mail", createdAt: getCreatedAt(24 * 9), category: "Communication", isRead: true, media: { kind: "icon", icon: Mail01Icon, tone: "destructive", }, }, ] export const notificationsQueryKey = ["notifications"] as const function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null } function isRandomUser(value: unknown): value is RandomUser { if (!isRecord(value) || !isRecord(value.name) || !isRecord(value.picture)) { return false } return ( typeof value.email === "string" && typeof value.name.first === "string" && typeof value.name.last === "string" && typeof value.picture.medium === "string" ) } function getUserName(user: RandomUser) { return `${user.name.first} ${user.name.last}` } function getAvatarMedia(user: RandomUser) { return { alt: getUserName(user), kind: "avatar" as const, src: user.picture.medium, } } function createRandomUserNotifications( users: readonly RandomUser[] ): readonly Notification[] { const [friend, mention, commenter, collaborator] = users if (!friend || !mention || !commenter || !collaborator) { throw new Error("Random User API returned too few users") } return [ { id: `friend-request:${friend.email}`, title: `${getUserName(friend)} sent you a friend request`, createdAt: getCreatedAt(11), category: "Communication", isRead: false, media: getAvatarMedia(friend), actions: [ { id: "accept", label: "Accept" }, { id: "decline", label: "Decline", intent: "neutral" }, ], }, { id: `mention:${mention.email}`, title: `${getUserName(mention)} mentioned you in Minimal UI`, createdAt: getCreatedAt(24), category: "Project UI", to: "/workspace/tasks", isRead: false, media: getAvatarMedia(mention), actions: [{ id: "view", label: "View", intent: "neutral" }], }, { id: `comment:${commenter.email}`, title: `${getUserName(commenter)} commented on your task`, description: "Can you review the latest changes?", createdAt: getCreatedAt(24 * 2), category: "Project UI", to: "/workspace/tasks", isRead: false, media: getAvatarMedia(commenter), }, { id: `collaborator:${collaborator.email}`, title: `${getUserName(collaborator)} joined your workspace`, createdAt: getCreatedAt(24 * 4), category: "Team", isRead: true, media: getAvatarMedia(collaborator), }, ...fallbackNotifications.slice(2), ] } export async function fetchMockNotifications({ signal, }: QueryFunctionContext): Promise { try { const response = await fetch(RANDOM_USER_API_URL, { signal }) if (!response.ok) { throw new Error(`Random User API responded with ${response.status}`) } const payload: unknown = await response.json() if (!isRecord(payload) || !Array.isArray(payload.results)) { throw new Error("Random User API returned an invalid response") } const users = payload.results.filter(isRandomUser) return createRandomUserNotifications(users) } catch (error) { if (signal.aborted) { throw error } return fallbackNotifications } }