// "Getting started" checklist for admins: each step is checked against the real state, not ticked by hand. import fs from "node:fs"; import path from "node:path"; import { DATA_DIR } from "./config.js"; import * as users from "./users.js"; import * as clients from "./clients.js"; import * as notify from "./notify.js"; import * as meta from "../../connector/src/meta.js"; import * as sched from "../../connector/src/schedule.js"; import * as lib from "../../connector/src/library.js"; import * as extra from "../../connector/src/platforms/index.js"; const FILE = path.join(DATA_DIR, "onboarding.json"); const read = () => { try { return JSON.parse(fs.readFileSync(FILE, "utf8")); } catch { return {}; } }; export async function steps() { let metaOk = false; try { metaOk = (await meta.listAccounts()).length > 0; } catch { /* not connected */ } const list = clients.listClients(); const posts = sched.listPosts({}); const portal = (() => { try { return Object.keys(JSON.parse(fs.readFileSync(path.join(DATA_DIR, "portal.json"), "utf8"))).length; } catch { return 0; } })(); const workspace = (() => { try { return JSON.parse(fs.readFileSync(path.join(DATA_DIR, "workspace.json"), "utf8")); } catch { return {}; } })(); const items = [ { id: "workspace", title: "Name your workspace", text: "Your agency's name and logo appear in the app, on client approval pages and in reports.", done: Boolean(workspace.name), link: "/settings#workspace" }, { id: "meta", title: "Connect Facebook and Instagram", text: "Add the Meta system user token to the server's .env (see the hosting guide). Every client's Page and Instagram account then shows up here.", done: metaOk, link: "/settings" }, { id: "client", title: "Add your first client", text: "Pick their Facebook Page or Instagram account from the list.", done: list.length > 0, link: "/" }, { id: "team", title: "Invite your team", text: "Add designers, editors and managers. Each gets their own login.", done: users.listUsers().length > 1, link: "/settings" }, { id: "platforms", title: "Connect another platform", text: "TikTok, YouTube, Google Business Profile, LinkedIn and more, per client.", done: extra.vault.listConnections({}).length > 0, link: "/connections" }, { id: "email", title: "Set up email", text: "So people get notified and clients get their approval emails and monthly reports.", done: notify.emailConfigured(), link: "/admin/health" }, { id: "library", title: "Upload finished work", text: "Designers upload to the Content library; an admin reviews it.", done: lib.listItems({}).length > 0, link: "/library" }, { id: "post", title: "Schedule and approve a post", text: "Create a draft, approve it, and Quorla publishes at the client's local time.", done: posts.some((p) => ["approved", "published", "partial"].includes(p.status)), link: "/publishing" }, { id: "portal", title: "Give a client their approval link", text: "They approve posts or ask for changes without a login.", done: portal > 0, link: "/" }, ]; return { dismissed: Boolean(read().dismissed), done: items.filter((s) => s.done).length, total: items.length, items }; } export function dismiss(value = true) { fs.writeFileSync(FILE, JSON.stringify({ ...read(), dismissed: Boolean(value), at: new Date().toISOString() })); }