Spaces:
Paused
Paused
Download data.js from EricaLuvGemma/olo: direct link, hf CLI and curl.
- Browser
- Download file 6.56 kB
-
https://huggingface.co/spaces/EricaLuvGemma/olo/resolve/main/data.js
- Command line
-
hf download hf://spaces/EricaLuvGemma/olo/data.js
-
curl -L -o data.js https://huggingface.co/spaces/EricaLuvGemma/olo/resolve/main/data.js
6.56 kB
| /* ============================================================ | |
| Shared state + mock data layer. | |
| Everything here reads/writes localStorage so the four screens | |
| can be clicked through without a backend. Swap the functions | |
| in this file for fetch() calls once the API exists — the | |
| shape of the returned objects is meant to match what the | |
| FastAPI endpoints will eventually return. | |
| ============================================================ */ | |
| const TIERS = { | |
| high_school: { label: "High school", desc: "Popular kid in a small pond" }, | |
| college: { label: "College", desc: "Building a name on campus" }, | |
| postgrad: { label: "Post-grad", desc: "Working the world at large" }, | |
| }; | |
| const ADJ = ["quiet", "bright", "lucky", "vivid", "loose", "sharp", "plain", "sunny", "faded", "wild"]; | |
| const NOUN = ["fern", "harbor", "kestrel", "static", "current", "atlas", "orbit", "linen", "ember", "gravel"]; | |
| function generateUsername(name){ | |
| const base = (name || "user").trim().split(/\s+/)[0].toLowerCase().replace(/[^a-z0-9]/g, ""); | |
| const word = NOUN[Math.floor(Math.random() * NOUN.length)]; | |
| const num = Math.floor(Math.random() * 89) + 10; | |
| return `${base || "user"}.${word}${num}`; | |
| } | |
| function getCharacter(){ | |
| const raw = localStorage.getItem("sf_character"); | |
| return raw ? JSON.parse(raw) : null; | |
| } | |
| function saveCharacter(c){ | |
| localStorage.setItem("sf_character", JSON.stringify(c)); | |
| } | |
| function requireOnboarding(){ | |
| if (!getCharacter()){ | |
| window.location.href = "onboarding.html"; | |
| } | |
| } | |
| function initials(name){ | |
| return (name || "?").trim().split(/\s+/).map(w => w[0]).slice(0,2).join("").toUpperCase(); | |
| } | |
| function timeAgo(ts){ | |
| const diff = Math.max(0, Date.now() - ts); | |
| const m = Math.floor(diff / 60000); | |
| if (m < 1) return "now"; | |
| if (m < 60) return `${m}m`; | |
| const h = Math.floor(m / 60); | |
| if (h < 24) return `${h}h`; | |
| return `${Math.floor(h / 24)}d`; | |
| } | |
| /* ---- NPC roster (shared across explore / dms / feed reactions) ---- */ | |
| const NPCS = [ | |
| { handle: "rae.holloway41", name: "Rae Holloway", role: "Class of 2027, front row energy", tier: "high_school" }, | |
| { handle: "denny.arc09", name: "Denny Okafor", role: "Runs the campus radio slot", tier: "college" }, | |
| { handle: "marlo.fenn77", name: "Marlo Fenn", role: "Small business owner, ships fast", tier: "postgrad" }, | |
| { handle: "pia.lund22", name: "Pia Lund", role: "Yearbook committee, sees everything", tier: "high_school" }, | |
| { handle: "theo.gravel14", name: "Theo Gravel", role: "Local news, campus desk", tier: "college" }, | |
| { handle: "wren.static88", name: "Wren Ashby", role: "Talent scout, always in your mentions", tier: "postgrad" }, | |
| { handle: "cole.ember03", name: "Cole Bishara", role: "Used to post a lot. Doesn't anymore.", tier: "high_school", retired: true }, | |
| ]; | |
| const NEWS_CHANNELS = [ | |
| { handle: "the.dispatch", name: "The Dispatch", role: "Local coverage, mostly rumor" }, | |
| { handle: "campus.wire", name: "Campus Wire", role: "Who's up, who's out" }, | |
| ]; | |
| function seedPosts(tier){ | |
| const now = Date.now(); | |
| return [ | |
| { | |
| id: "p1", | |
| author: NPCS[0], | |
| body: "spent four hours on a project due tomorrow and used none of it wisely", | |
| ts: now - 1000 * 60 * 42, | |
| seen: 118, followed: 34, likes: 22, | |
| comments: [ | |
| { author: NPCS[3], body: "this is a weekly occurrence at this point" }, | |
| { author: NPCS[1], body: "same energy every single time" }, | |
| ], | |
| }, | |
| { | |
| id: "p2", | |
| author: NPCS[2], | |
| body: "small batch of the candles restocked. shipping starts friday if anyone wants in", | |
| ts: now - 1000 * 60 * 60 * 3, | |
| seen: 203, followed: 61, likes: 47, | |
| comments: [ | |
| { author: NPCS[4], body: "these sold out last time in about a day" }, | |
| ], | |
| }, | |
| { | |
| id: "p3", | |
| author: NPCS[6], | |
| body: "i remember when i thought i was the main character. couldn't make it as a social media giant. be careful what you believe online", | |
| ts: now - 1000 * 60 * 60 * 20, | |
| seen: 76, followed: 12, likes: 9, | |
| comments: [], | |
| retired: true, | |
| }, | |
| ]; | |
| } | |
| function seedDMs(){ | |
| const now = Date.now(); | |
| return [ | |
| { | |
| handle: NPCS[2].handle, | |
| unread: true, | |
| messages: [ | |
| { from: "them", body: "hey, saw your posts. if you send a few of my products around and it lands, I'll cover you for it.", ts: now - 1000 * 60 * 50 }, | |
| ], | |
| }, | |
| { | |
| handle: NPCS[0].handle, | |
| unread: false, | |
| messages: [ | |
| { from: "them", body: "you coming to the thing friday", ts: now - 1000 * 60 * 60 * 5 }, | |
| { from: "me", body: "thinking about it", ts: now - 1000 * 60 * 60 * 4 }, | |
| ], | |
| }, | |
| { | |
| handle: NPCS[5].handle, | |
| unread: true, | |
| messages: [ | |
| { from: "them", body: "your numbers this week are worth a real conversation. free later?", ts: now - 1000 * 60 * 60 * 9 }, | |
| ], | |
| }, | |
| ]; | |
| } | |
| function getPosts(){ | |
| let raw = localStorage.getItem("sf_posts"); | |
| if (!raw){ | |
| const seeded = seedPosts(); | |
| localStorage.setItem("sf_posts", JSON.stringify(seeded)); | |
| return seeded; | |
| } | |
| return JSON.parse(raw); | |
| } | |
| function savePosts(posts){ | |
| localStorage.setItem("sf_posts", JSON.stringify(posts)); | |
| } | |
| function getDMs(){ | |
| let raw = localStorage.getItem("sf_dms"); | |
| if (!raw){ | |
| const seeded = seedDMs(); | |
| localStorage.setItem("sf_dms", JSON.stringify(seeded)); | |
| return seeded; | |
| } | |
| return JSON.parse(raw); | |
| } | |
| function saveDMs(dms){ | |
| localStorage.setItem("sf_dms", JSON.stringify(dms)); | |
| } | |
| function npcByHandle(handle){ | |
| return NPCS.find(n => n.handle === handle) || NEWS_CHANNELS.find(n => n.handle === handle); | |
| } | |
| /* ---- likes ---- */ | |
| function getLikedIds(){ | |
| const raw = localStorage.getItem("sf_likes"); | |
| return raw ? JSON.parse(raw) : []; | |
| } | |
| function saveLikedIds(ids){ | |
| localStorage.setItem("sf_likes", JSON.stringify(ids)); | |
| } | |
| /* Toggles the like on a post for the current user, persists both the | |
| post's like count and the user's liked-id set, and returns the | |
| updated { liked, likes } so the caller can update the DOM in place. */ | |
| function toggleLike(postId){ | |
| const posts = getPosts(); | |
| const post = posts.find(p => p.id === postId); | |
| if (!post) return null; | |
| let liked = getLikedIds(); | |
| const isLiked = liked.includes(postId); | |
| if (isLiked){ | |
| liked = liked.filter(id => id !== postId); | |
| post.likes = Math.max(0, (post.likes || 0) - 1); | |
| } else { | |
| liked.push(postId); | |
| post.likes = (post.likes || 0) + 1; | |
| } | |
| saveLikedIds(liked); | |
| savePosts(posts); | |
| return { liked: !isLiked, likes: post.likes }; | |
| } | |