@robbiesrobotics/alice-agents 1.5.8 โ 1.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -129
- package/bin/alice-install.mjs +27 -35
- package/lib/hermes-agent.mjs +449 -0
- package/lib/hermes-installer.mjs +338 -0
- package/lib/installer.mjs +254 -19
- package/lib/skills.mjs +128 -4
- package/package.json +3 -3
- package/templates/skills/acculynx/SKILL.md +183 -0
- package/templates/skills/acculynx/references/analysis_template.py +116 -0
- package/templates/skills/acculynx/references/dashboard_page.tsx +641 -0
- package/templates/skills/claude-code/SKILL.md +2 -2
- package/templates/skills/coding-agent/SKILL.md +68 -0
- package/templates/skills/crawl4ai/SKILL.md +119 -0
- package/templates/skills/crawl4ai/scripts/crwl +3 -0
- package/templates/workspaces/_shared/AGENTS-hermes.md +54 -0
- package/templates/workspaces/_shared/AGENTS.md +25 -0
- package/templates/workspaces/_shared/SOUL-hermes.md +35 -0
- package/templates/workspaces/_shared/hermes-agent-skill.md +40 -0
- package/templates/workspaces/_shared/hermes-orchestrator-skill.md +150 -0
- package/templates/workspaces/_shared/hermes-specialist-skill.md +109 -0
- package/templates/workspaces/accuscope/AGENTS.md +38 -0
- package/templates/workspaces/accuscope/FEEDBACK.md +27 -0
- package/templates/workspaces/accuscope/HEARTBEAT.md +26 -0
- package/templates/workspaces/accuscope/IDENTITY.md +48 -0
- package/templates/workspaces/accuscope/LEARNINGS.md +46 -0
- package/templates/workspaces/accuscope/MEMORY.md +47 -0
- package/templates/workspaces/accuscope/PLAYBOOK.md +65 -0
- package/templates/workspaces/accuscope/SOUL.md +40 -0
- package/templates/workspaces/accuscope/TOOLS.md +63 -0
- package/templates/workspaces/accuscope/USER.md +39 -0
- package/templates/workspaces/aiden/AGENTS.md +52 -0
- package/templates/workspaces/aiden/FEEDBACK.md +12 -0
- package/templates/workspaces/aiden/HEARTBEAT.md +9 -0
- package/templates/workspaces/aiden/IDENTITY.md +6 -0
- package/templates/workspaces/aiden/LEARNINGS.md +6 -0
- package/templates/workspaces/aiden/MEMORY.md +22 -0
- package/templates/workspaces/aiden/PLAYBOOK.md +16 -0
- package/templates/workspaces/aiden/SOUL.md +1 -1
- package/templates/workspaces/aiden/USER.md +17 -0
- package/templates/workspaces/alex/AGENTS.md +52 -0
- package/templates/workspaces/alex/FEEDBACK.md +11 -0
- package/templates/workspaces/alex/HEARTBEAT.md +9 -0
- package/templates/workspaces/alex/IDENTITY.md +6 -0
- package/templates/workspaces/alex/LEARNINGS.md +5 -0
- package/templates/workspaces/alex/MEMORY.md +22 -0
- package/templates/workspaces/alex/PLAYBOOK.md +16 -0
- package/templates/workspaces/alex/SOUL.md +1 -1
- package/templates/workspaces/alex/USER.md +13 -0
- package/templates/workspaces/aria/AGENTS.md +18 -0
- package/templates/workspaces/aria/FEEDBACK.md +12 -0
- package/templates/workspaces/aria/HEARTBEAT.md +32 -0
- package/templates/workspaces/aria/IDENTITY.md +12 -0
- package/templates/workspaces/aria/LEARNINGS.md +31 -0
- package/templates/workspaces/aria/MEMORY.md +29 -0
- package/templates/workspaces/aria/PLAYBOOK.md +71 -0
- package/templates/workspaces/aria/SOUL.md +57 -0
- package/templates/workspaces/aria/TOOLS.md +47 -0
- package/templates/workspaces/aria/USER.md +18 -0
- package/templates/workspaces/audrey/AGENTS.md +59 -0
- package/templates/workspaces/audrey/FEEDBACK.md +11 -0
- package/templates/workspaces/audrey/HEARTBEAT.md +9 -0
- package/templates/workspaces/audrey/IDENTITY.md +6 -0
- package/templates/workspaces/audrey/LEARNINGS.md +5 -0
- package/templates/workspaces/audrey/MEMORY.md +22 -0
- package/templates/workspaces/audrey/PLAYBOOK.md +16 -0
- package/templates/workspaces/audrey/SOUL.md +1 -1
- package/templates/workspaces/audrey/TOOLS.md +15 -0
- package/templates/workspaces/audrey/USER.md +13 -0
- package/templates/workspaces/avery/AGENTS.md +52 -0
- package/templates/workspaces/avery/FEEDBACK.md +12 -0
- package/templates/workspaces/avery/HEARTBEAT.md +5 -0
- package/templates/workspaces/avery/IDENTITY.md +6 -0
- package/templates/workspaces/avery/LEARNINGS.md +6 -0
- package/templates/workspaces/avery/MEMORY.md +22 -0
- package/templates/workspaces/avery/PLAYBOOK.md +16 -0
- package/templates/workspaces/avery/SOUL.md +1 -1
- package/templates/workspaces/avery/USER.md +17 -0
- package/templates/workspaces/avery/skills/claude-code/SKILL.md +38 -0
- package/templates/workspaces/avery/skills/claude-code/claude_code +55 -0
- package/templates/workspaces/caleb/AGENTS.md +52 -0
- package/templates/workspaces/caleb/FEEDBACK.md +11 -0
- package/templates/workspaces/caleb/HEARTBEAT.md +9 -0
- package/templates/workspaces/caleb/IDENTITY.md +6 -0
- package/templates/workspaces/caleb/LEARNINGS.md +5 -0
- package/templates/workspaces/caleb/MEMORY.md +22 -0
- package/templates/workspaces/caleb/PLAYBOOK.md +16 -0
- package/templates/workspaces/caleb/SOUL.md +1 -1
- package/templates/workspaces/caleb/TOOLS.md +30 -0
- package/templates/workspaces/caleb/USER.md +13 -0
- package/templates/workspaces/clara/AGENTS.md +59 -0
- package/templates/workspaces/clara/FEEDBACK.md +12 -0
- package/templates/workspaces/clara/HEARTBEAT.md +5 -0
- package/templates/workspaces/clara/IDENTITY.md +6 -0
- package/templates/workspaces/clara/LEARNINGS.md +6 -0
- package/templates/workspaces/clara/MEMORY.md +22 -0
- package/templates/workspaces/clara/PLAYBOOK.md +16 -0
- package/templates/workspaces/clara/SOUL.md +1 -1
- package/templates/workspaces/clara/TOOLS.md +15 -0
- package/templates/workspaces/clara/USER.md +17 -0
- package/templates/workspaces/daphne/AGENTS.md +59 -0
- package/templates/workspaces/daphne/FEEDBACK.md +18 -0
- package/templates/workspaces/daphne/HEARTBEAT.md +5 -0
- package/templates/workspaces/daphne/IDENTITY.md +6 -0
- package/templates/workspaces/daphne/LEARNINGS.md +6 -0
- package/templates/workspaces/daphne/MEMORY.md +22 -0
- package/templates/workspaces/daphne/PLAYBOOK.md +48 -0
- package/templates/workspaces/daphne/SOUL.md +1 -1
- package/templates/workspaces/daphne/TOOLS.md +15 -0
- package/templates/workspaces/daphne/USER.md +17 -0
- package/templates/workspaces/darius/AGENTS.md +52 -0
- package/templates/workspaces/darius/FEEDBACK.md +12 -0
- package/templates/workspaces/darius/HEARTBEAT.md +5 -0
- package/templates/workspaces/darius/IDENTITY.md +6 -0
- package/templates/workspaces/darius/LEARNINGS.md +6 -0
- package/templates/workspaces/darius/MEMORY.md +22 -0
- package/templates/workspaces/darius/PLAYBOOK.md +16 -0
- package/templates/workspaces/darius/SOUL.md +1 -1
- package/templates/workspaces/darius/USER.md +17 -0
- package/templates/workspaces/darius/skills/claude-code/SKILL.md +38 -0
- package/templates/workspaces/darius/skills/claude-code/claude_code +55 -0
- package/templates/workspaces/devon/AGENTS.md +52 -0
- package/templates/workspaces/devon/FEEDBACK.md +11 -0
- package/templates/workspaces/devon/HEARTBEAT.md +5 -0
- package/templates/workspaces/devon/IDENTITY.md +6 -0
- package/templates/workspaces/devon/LEARNINGS.md +11 -0
- package/templates/workspaces/devon/MEMORY.md +22 -0
- package/templates/workspaces/devon/PLAYBOOK.md +16 -0
- package/templates/workspaces/devon/SOUL.md +1 -1
- package/templates/workspaces/devon/USER.md +13 -0
- package/templates/workspaces/devon/check_github.py +12 -0
- package/templates/workspaces/devon/check_mc_env.py +30 -0
- package/templates/workspaces/devon/check_sb.py +34 -0
- package/templates/workspaces/devon/check_vercel.py +12 -0
- package/templates/workspaces/devon/get_mc_files.py +17 -0
- package/templates/workspaces/devon/write_heartbeat.py +67 -0
- package/templates/workspaces/dylan/.env.example +33 -0
- package/templates/workspaces/dylan/00007_verify_licenses_table.sql +100 -0
- package/templates/workspaces/dylan/AGENTS.md +52 -0
- package/templates/workspaces/dylan/FEEDBACK.md +28 -0
- package/templates/workspaces/dylan/HEARTBEAT.md +5 -0
- package/templates/workspaces/dylan/IDENTITY.md +6 -0
- package/templates/workspaces/dylan/LEARNINGS.md +70 -0
- package/templates/workspaces/dylan/MEMORY.md +22 -0
- package/templates/workspaces/dylan/PLAYBOOK.md +16 -0
- package/templates/workspaces/dylan/SOUL.md +1 -1
- package/templates/workspaces/dylan/STRIPE_PIPELINE.md +185 -0
- package/templates/workspaces/dylan/USER.md +17 -0
- package/templates/workspaces/dylan/n8n-stripe-welcome-workflow.json +123 -0
- package/templates/workspaces/dylan/skills/claude-code/SKILL.md +38 -0
- package/templates/workspaces/dylan/skills/claude-code/claude_code +55 -0
- package/templates/workspaces/dylan/stripe-webhook-handler.py +433 -0
- package/templates/workspaces/dylan/test_mock_webhook.py +103 -0
- package/templates/workspaces/elena/AGENTS.md +59 -0
- package/templates/workspaces/elena/FEEDBACK.md +11 -0
- package/templates/workspaces/elena/HEARTBEAT.md +9 -0
- package/templates/workspaces/elena/IDENTITY.md +6 -0
- package/templates/workspaces/elena/LEARNINGS.md +5 -0
- package/templates/workspaces/elena/MEMORY.md +22 -0
- package/templates/workspaces/elena/PLAYBOOK.md +16 -0
- package/templates/workspaces/elena/SOUL.md +1 -1
- package/templates/workspaces/elena/TOOLS.md +15 -0
- package/templates/workspaces/elena/USER.md +13 -0
- package/templates/workspaces/eva/AGENTS.md +59 -0
- package/templates/workspaces/eva/FEEDBACK.md +11 -0
- package/templates/workspaces/eva/HEARTBEAT.md +9 -0
- package/templates/workspaces/eva/IDENTITY.md +6 -0
- package/templates/workspaces/eva/LEARNINGS.md +5 -0
- package/templates/workspaces/eva/MEMORY.md +22 -0
- package/templates/workspaces/eva/PLAYBOOK.md +16 -0
- package/templates/workspaces/eva/SOUL.md +1 -1
- package/templates/workspaces/eva/TOOLS.md +15 -0
- package/templates/workspaces/eva/USER.md +13 -0
- package/templates/workspaces/felix/AGENTS.md +52 -0
- package/templates/workspaces/felix/FEEDBACK.md +11 -0
- package/templates/workspaces/felix/HEARTBEAT.md +5 -0
- package/templates/workspaces/felix/IDENTITY.md +6 -0
- package/templates/workspaces/felix/LEARNINGS.md +17 -0
- package/templates/workspaces/felix/MEMORY.md +22 -0
- package/templates/workspaces/felix/PLAYBOOK.md +16 -0
- package/templates/workspaces/felix/SOUL.md +1 -1
- package/templates/workspaces/felix/USER.md +13 -0
- package/templates/workspaces/felix/fidelia-psychology.html +1594 -0
- package/templates/workspaces/felix/task.txt +164 -0
- package/templates/workspaces/hannah/AGENTS.md +59 -0
- package/templates/workspaces/hannah/FEEDBACK.md +12 -0
- package/templates/workspaces/hannah/HEARTBEAT.md +5 -0
- package/templates/workspaces/hannah/IDENTITY.md +6 -0
- package/templates/workspaces/hannah/LEARNINGS.md +6 -0
- package/templates/workspaces/hannah/MEMORY.md +22 -0
- package/templates/workspaces/hannah/PLAYBOOK.md +16 -0
- package/templates/workspaces/hannah/SOUL.md +1 -1
- package/templates/workspaces/hannah/TOOLS.md +15 -0
- package/templates/workspaces/hannah/USER.md +17 -0
- package/templates/workspaces/isaac/AGENTS.md +52 -0
- package/templates/workspaces/isaac/FEEDBACK.md +12 -0
- package/templates/workspaces/isaac/HEARTBEAT.md +9 -0
- package/templates/workspaces/isaac/IDENTITY.md +6 -0
- package/templates/workspaces/isaac/LEARNINGS.md +6 -0
- package/templates/workspaces/isaac/MEMORY.md +22 -0
- package/templates/workspaces/isaac/PLAYBOOK.md +16 -0
- package/templates/workspaces/isaac/SOUL.md +1 -1
- package/templates/workspaces/isaac/USER.md +17 -0
- package/templates/workspaces/isaac/skills/claude-code/SKILL.md +38 -0
- package/templates/workspaces/isaac/skills/claude-code/claude_code +55 -0
- package/templates/workspaces/logan/AGENTS.md +59 -0
- package/templates/workspaces/logan/FEEDBACK.md +11 -0
- package/templates/workspaces/logan/HEARTBEAT.md +9 -0
- package/templates/workspaces/logan/IDENTITY.md +6 -0
- package/templates/workspaces/logan/LEARNINGS.md +5 -0
- package/templates/workspaces/logan/MEMORY.md +22 -0
- package/templates/workspaces/logan/PLAYBOOK.md +16 -0
- package/templates/workspaces/logan/SOUL.md +1 -1
- package/templates/workspaces/logan/TOOLS.md +15 -0
- package/templates/workspaces/logan/USER.md +13 -0
- package/templates/workspaces/maxxipro/AGENTS.md +29 -0
- package/templates/workspaces/maxxipro/FEEDBACK.md +19 -0
- package/templates/workspaces/maxxipro/HEARTBEAT.md +22 -0
- package/templates/workspaces/maxxipro/IDENTITY.md +35 -0
- package/templates/workspaces/maxxipro/KNOWLEDGE.md +335 -0
- package/templates/workspaces/maxxipro/LEARNINGS.md +47 -0
- package/templates/workspaces/maxxipro/MEMORY.md +60 -0
- package/templates/workspaces/maxxipro/OUTREACH_TEMPLATES.md +143 -0
- package/templates/workspaces/maxxipro/PLAYBOOK.md +81 -0
- package/templates/workspaces/maxxipro/SOUL.md +146 -0
- package/templates/workspaces/maxxipro/TOOLS.md +81 -0
- package/templates/workspaces/maxxipro/USER.md +40 -0
- package/templates/workspaces/morgan/AGENTS.md +59 -0
- package/templates/workspaces/morgan/FEEDBACK.md +19 -0
- package/templates/workspaces/morgan/HEARTBEAT.md +5 -0
- package/templates/workspaces/morgan/IDENTITY.md +6 -0
- package/templates/workspaces/morgan/LEARNINGS.md +18 -0
- package/templates/workspaces/morgan/MEMORY.md +22 -0
- package/templates/workspaces/morgan/PLAYBOOK.md +16 -0
- package/templates/workspaces/morgan/SOUL.md +1 -1
- package/templates/workspaces/morgan/TOOLS.md +15 -0
- package/templates/workspaces/morgan/USER.md +13 -0
- package/templates/workspaces/nadia/AGENTS.md +59 -0
- package/templates/workspaces/nadia/FEEDBACK.md +12 -0
- package/templates/workspaces/nadia/HEARTBEAT.md +5 -0
- package/templates/workspaces/nadia/IDENTITY.md +6 -0
- package/templates/workspaces/nadia/LEARNINGS.md +6 -0
- package/templates/workspaces/nadia/MEMORY.md +22 -0
- package/templates/workspaces/nadia/PLAYBOOK.md +16 -0
- package/templates/workspaces/nadia/SOUL.md +1 -1
- package/templates/workspaces/nadia/TOOLS.md +15 -0
- package/templates/workspaces/nadia/USER.md +13 -0
- package/templates/workspaces/nate/AGENTS.md +24 -0
- package/templates/workspaces/nate/FEEDBACK.md +12 -0
- package/templates/workspaces/nate/HEARTBEAT.md +33 -0
- package/templates/workspaces/nate/IDENTITY.md +15 -0
- package/templates/workspaces/nate/LEARNINGS.md +33 -0
- package/templates/workspaces/nate/MEMORY.md +39 -0
- package/templates/workspaces/nate/PLAYBOOK.md +160 -0
- package/templates/workspaces/nate/SOUL.md +50 -0
- package/templates/workspaces/nate/TOOLS.md +111 -0
- package/templates/workspaces/nate/USER.md +32 -0
- package/templates/workspaces/olivia/.last-openclaw-version +1 -0
- package/templates/workspaces/olivia/.npmrc.tmp +0 -0
- package/templates/workspaces/olivia/AGENTS.md +77 -0
- package/templates/workspaces/olivia/ALPHA_CODING_BENCHMARK.txt +148 -0
- package/templates/workspaces/olivia/ALPHA_MODEL_GUIDE.md +393 -0
- package/templates/workspaces/olivia/FEEDBACK.md +13 -0
- package/templates/workspaces/olivia/HEADTOHEAD_BENCHMARK.txt +1289 -0
- package/templates/workspaces/olivia/HEARTBEAT.md +267 -0
- package/templates/workspaces/olivia/IDENTITY.md +6 -0
- package/templates/workspaces/olivia/LEARNINGS.md +708 -0
- package/templates/workspaces/olivia/MEMORY.md +202 -0
- package/templates/workspaces/olivia/MISSION_CONTROL_DESIGN_SPEC_v1.md +1143 -0
- package/templates/workspaces/olivia/MVP-COMPLETION-SUMMARY.md +175 -0
- package/templates/workspaces/olivia/NETWORK_IMPLEMENTATION_PLAN.md +1556 -0
- package/templates/workspaces/olivia/NEW_NODES_BENCHMARK.txt +947 -0
- package/templates/workspaces/olivia/PLAYBOOK.md +42 -0
- package/templates/workspaces/olivia/SELF-HEALING-COMPLETE.md +150 -0
- package/templates/workspaces/olivia/SOUL.md +8 -8
- package/templates/workspaces/olivia/TOOLS.md +15 -0
- package/templates/workspaces/olivia/USER.md +17 -0
- package/templates/workspaces/olivia/alicefleet-supabase-credentials.md +50 -0
- package/templates/workspaces/olivia/dzombo-copy-rewrite.md +115 -0
- package/templates/workspaces/olivia/dzombo-implementation-plan.md +1248 -0
- package/templates/workspaces/olivia/fidelia-psychology.html +1594 -0
- package/templates/workspaces/olivia/lead_debug.png +0 -0
- package/templates/workspaces/olivia/minimatch-10.2.4.tgz +0 -0
- package/templates/workspaces/olivia/operation-bllm-research.md +157 -0
- package/templates/workspaces/olivia/qa-audit-mission-control-v2.md +538 -0
- package/templates/workspaces/olivia/roofmaxx_logo.svg +1 -0
- package/templates/workspaces/olivia/roofmaxx_social.jpg +0 -0
- package/templates/workspaces/olivia/skills/1password/SKILL.md +53 -0
- package/templates/workspaces/olivia/skills/1password/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/afrexai-recruiting-engine/README.md +57 -0
- package/templates/workspaces/olivia/skills/afrexai-recruiting-engine/SKILL.md +534 -0
- package/templates/workspaces/olivia/skills/afrexai-recruiting-engine/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/agent-security/SKILL.md +69 -0
- package/templates/workspaces/olivia/skills/agent-security/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/agentic-security-audit/SKILL.md +855 -0
- package/templates/workspaces/olivia/skills/agentic-security-audit/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-automation-consulting/SKILL.md +67 -0
- package/templates/workspaces/olivia/skills/ai-automation-consulting/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-automation-consulting/skill.json +12 -0
- package/templates/workspaces/olivia/skills/ai-presentation-maker/SKILL.md +1104 -0
- package/templates/workspaces/olivia/skills/ai-presentation-maker/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-productivity-audit/SKILL.md +181 -0
- package/templates/workspaces/olivia/skills/ai-productivity-audit/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-researcher/README.md +31 -0
- package/templates/workspaces/olivia/skills/ai-researcher/SKILL.md +59 -0
- package/templates/workspaces/olivia/skills/ai-researcher/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-seo-writer/README.md +19 -0
- package/templates/workspaces/olivia/skills/ai-seo-writer/SKILL.md +100 -0
- package/templates/workspaces/olivia/skills/ai-seo-writer/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/analytics-tracking-2/SKILL.md +309 -0
- package/templates/workspaces/olivia/skills/analytics-tracking-2/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/api-doc-writer/SKILL.md +232 -0
- package/templates/workspaces/olivia/skills/api-doc-writer/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/api-generator/SKILL.md +49 -0
- package/templates/workspaces/olivia/skills/api-generator/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/api-generator/tips.md +10 -0
- package/templates/workspaces/olivia/skills/apple-notes/SKILL.md +50 -0
- package/templates/workspaces/olivia/skills/apple-notes/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/apple-reminders/SKILL.md +67 -0
- package/templates/workspaces/olivia/skills/apple-reminders/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/automation-workflows/SKILL.md +267 -0
- package/templates/workspaces/olivia/skills/automation-workflows/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/autoresearch/SKILL.md +46 -0
- package/templates/workspaces/olivia/skills/autoresearch/aria_write.py +148 -0
- package/templates/workspaces/olivia/skills/autoresearch/autoresearch.py +75 -0
- package/templates/workspaces/olivia/skills/azure-devops/SKILL.md +115 -0
- package/templates/workspaces/olivia/skills/azure-devops/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/blogwatcher/SKILL.md +46 -0
- package/templates/workspaces/olivia/skills/blogwatcher/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/blucli/SKILL.md +27 -0
- package/templates/workspaces/olivia/skills/blucli/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/check-analytics/SKILL.md +92 -0
- package/templates/workspaces/olivia/skills/check-analytics/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/cloud-architect/SKILL.md +89 -0
- package/templates/workspaces/olivia/skills/cloud-architect/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/cloud-infra-automation/SKILL.md +50 -0
- package/templates/workspaces/olivia/skills/cloud-infra-automation/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/cloud-storage/SKILL.md +61 -0
- package/templates/workspaces/olivia/skills/cloud-storage/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/cloud-storage/auth.md +97 -0
- package/templates/workspaces/olivia/skills/cloud-storage/costs.md +88 -0
- package/templates/workspaces/olivia/skills/cloud-storage/providers.md +55 -0
- package/templates/workspaces/olivia/skills/copywriting-pro/SKILL.md +107 -0
- package/templates/workspaces/olivia/skills/copywriting-pro/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/data-analyst-pro/SKILL.md +21 -0
- package/templates/workspaces/olivia/skills/data-analyst-pro/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/database-designer/README.md +388 -0
- package/templates/workspaces/olivia/skills/database-designer/SKILL.md +66 -0
- package/templates/workspaces/olivia/skills/database-designer/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/database-designer/index_optimizer.py +926 -0
- package/templates/workspaces/olivia/skills/database-designer/migration_generator.py +1199 -0
- package/templates/workspaces/olivia/skills/database-designer/schema_analyzer.py +982 -0
- package/templates/workspaces/olivia/skills/deploy-agent/SKILL.md +255 -0
- package/templates/workspaces/olivia/skills/deploy-agent/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/devops-automation-pack/SKILL.md +72 -0
- package/templates/workspaces/olivia/skills/devops-automation-pack/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/devops-automation-pack/deploy.sh +0 -0
- package/templates/workspaces/olivia/skills/financial-analysis-agent/SKILL.md +489 -0
- package/templates/workspaces/olivia/skills/financial-analysis-agent/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/gdpr-compliance-tracker/README.md +72 -0
- package/templates/workspaces/olivia/skills/gdpr-compliance-tracker/SKILL.md +226 -0
- package/templates/workspaces/olivia/skills/gdpr-compliance-tracker/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/gifgrep/SKILL.md +47 -0
- package/templates/workspaces/olivia/skills/gifgrep/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/github/SKILL.md +47 -0
- package/templates/workspaces/olivia/skills/github/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/gog/SKILL.md +36 -0
- package/templates/workspaces/olivia/skills/gog/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/growth-strategy-hub/SKILL.md +135 -0
- package/templates/workspaces/olivia/skills/growth-strategy-hub/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/growth-strategy-hub/metadata.json +4 -0
- package/templates/workspaces/olivia/skills/hetzner-cloud/SKILL.md +130 -0
- package/templates/workspaces/olivia/skills/hetzner-cloud/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/himalaya/SKILL.md +217 -0
- package/templates/workspaces/olivia/skills/himalaya/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/hotel-recommendation/SKILL.md +117 -0
- package/templates/workspaces/olivia/skills/hotel-recommendation/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/hr-policy-generator/SKILL.md +54 -0
- package/templates/workspaces/olivia/skills/hr-policy-generator/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/human-writing/SKILL.md +41 -0
- package/templates/workspaces/olivia/skills/human-writing/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/imsg/SKILL.md +25 -0
- package/templates/workspaces/olivia/skills/imsg/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/in-depth-research/SKILL.md +124 -0
- package/templates/workspaces/olivia/skills/in-depth-research/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/in-depth-research/methodology.md +75 -0
- package/templates/workspaces/olivia/skills/in-depth-research/output-formats.md +168 -0
- package/templates/workspaces/olivia/skills/in-depth-research/sources.md +80 -0
- package/templates/workspaces/olivia/skills/javascript-skills/README.md +71 -0
- package/templates/workspaces/olivia/skills/javascript-skills/SKILL.md +746 -0
- package/templates/workspaces/olivia/skills/javascript-skills/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/leadership-strategy-playbook/SKILL.md +147 -0
- package/templates/workspaces/olivia/skills/leadership-strategy-playbook/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/market-research-agent/README.md +29 -0
- package/templates/workspaces/olivia/skills/market-research-agent/SKILL.md +52 -0
- package/templates/workspaces/olivia/skills/market-research-agent/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/marketing-analytics/SKILL.md +74 -0
- package/templates/workspaces/olivia/skills/marketing-analytics/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/marketing-master-io/SKILL.md +125 -0
- package/templates/workspaces/olivia/skills/marketing-master-io/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/marketing-strategy-pmm/SKILL.md +398 -0
- package/templates/workspaces/olivia/skills/marketing-strategy-pmm/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/meta-ads-analytics/SKILL.md +53 -0
- package/templates/workspaces/olivia/skills/meta-ads-analytics/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/obsidian/SKILL.md +55 -0
- package/templates/workspaces/olivia/skills/obsidian/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/openclaw-accounting/SKILL.md +125 -0
- package/templates/workspaces/olivia/skills/openclaw-accounting/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/CHANGELOG.md +35 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/CHANNELLOG.md +73 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/README.md +161 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/SKILL.md +130 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/config.json +36 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/metadata.json +19 -0
- package/templates/workspaces/olivia/skills/openhue/SKILL.md +30 -0
- package/templates/workspaces/olivia/skills/openhue/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/orgx-operations-agent/SKILL.md +41 -0
- package/templates/workspaces/olivia/skills/orgx-operations-agent/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/outreach/SKILL.md +84 -0
- package/templates/workspaces/olivia/skills/outreach/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/outreach/by-type.md +166 -0
- package/templates/workspaces/olivia/skills/outreach/templates.md +154 -0
- package/templates/workspaces/olivia/skills/outreach/tracking.md +145 -0
- package/templates/workspaces/olivia/skills/persona-hr-coordinator/SKILL.md +38 -0
- package/templates/workspaces/olivia/skills/persona-hr-coordinator/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/personal-productivity/SKILL.md +161 -0
- package/templates/workspaces/olivia/skills/personal-productivity/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/personal-productivity/index.js +363 -0
- package/templates/workspaces/olivia/skills/personal-productivity/package.json +15 -0
- package/templates/workspaces/olivia/skills/personal-travel/README.md +34 -0
- package/templates/workspaces/olivia/skills/personal-travel/SKILL.md +46 -0
- package/templates/workspaces/olivia/skills/personal-travel/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/presentation-html-generator-skill/SKILL.md +185 -0
- package/templates/workspaces/olivia/skills/presentation-html-generator-skill/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/product-manager/SKILL.md +77 -0
- package/templates/workspaces/olivia/skills/product-manager/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/quant-strategy/SKILL.md +28 -0
- package/templates/workspaces/olivia/skills/quant-strategy/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/sales-pipeline-tracker/README.md +29 -0
- package/templates/workspaces/olivia/skills/sales-pipeline-tracker/SKILL.md +45 -0
- package/templates/workspaces/olivia/skills/sales-pipeline-tracker/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/security-auditor/SKILL.md +399 -0
- package/templates/workspaces/olivia/skills/security-auditor/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/security-hardening/SKILL.md +296 -0
- package/templates/workspaces/olivia/skills/security-hardening/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/security-scanner/SKILL.md +67 -0
- package/templates/workspaces/olivia/skills/security-scanner/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/seo-optimization/SKILL.md +31 -0
- package/templates/workspaces/olivia/skills/seo-optimization/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/service-booking/SKILL.md +193 -0
- package/templates/workspaces/olivia/skills/service-booking/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/sme-hr-automation/SKILL.md +131 -0
- package/templates/workspaces/olivia/skills/sme-hr-automation/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/social-media-scheduler/README.md +29 -0
- package/templates/workspaces/olivia/skills/social-media-scheduler/SKILL.md +49 -0
- package/templates/workspaces/olivia/skills/social-media-scheduler/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/sonoscli/SKILL.md +26 -0
- package/templates/workspaces/olivia/skills/sonoscli/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/strategy-advisor/SKILL.md +33 -0
- package/templates/workspaces/olivia/skills/strategy-advisor/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/summarize/SKILL.md +49 -0
- package/templates/workspaces/olivia/skills/summarize/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/things-mac/SKILL.md +61 -0
- package/templates/workspaces/olivia/skills/things-mac/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/travel-itinerary-planner/SKILL.md +121 -0
- package/templates/workspaces/olivia/skills/travel-itinerary-planner/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/travel-manager/SKILL.md +36 -0
- package/templates/workspaces/olivia/skills/travel-manager/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/travel-planning/SKILL.md +238 -0
- package/templates/workspaces/olivia/skills/travel-planning/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/travel-planning/booking-guide.md +91 -0
- package/templates/workspaces/olivia/skills/travel-planning/memory-template.md +111 -0
- package/templates/workspaces/olivia/skills/travel-planning/multi-city.md +131 -0
- package/templates/workspaces/olivia/skills/travel-planning/packing-templates.md +155 -0
- package/templates/workspaces/olivia/skills/travel-planning/setup.md +66 -0
- package/templates/workspaces/olivia/skills/update-it-all/SKILL.md +143 -0
- package/templates/workspaces/olivia/skills/update-it-all/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/voice/SKILL.md +62 -0
- package/templates/workspaces/olivia/skills/weather/SKILL.md +49 -0
- package/templates/workspaces/olivia/skills/weather/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/web-researcher/SKILL.md +21 -0
- package/templates/workspaces/olivia/skills/web-researcher/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/website-seo/SKILL.md +284 -0
- package/templates/workspaces/olivia/skills/website-seo/_meta.json +6 -0
- package/templates/workspaces/olivia/stripe-welcome-n8n.json +103 -0
- package/templates/workspaces/olivia/test2.wav.wav +0 -0
- package/templates/workspaces/olivia/test_speech.json +1 -0
- package/templates/workspaces/olivia/test_speech.srt +0 -0
- package/templates/workspaces/olivia/test_speech.tsv +1 -0
- package/templates/workspaces/olivia/test_speech.txt +0 -0
- package/templates/workspaces/olivia/test_speech.vtt +2 -0
- package/templates/workspaces/owen/AGENTS.md +59 -0
- package/templates/workspaces/owen/FEEDBACK.md +12 -0
- package/templates/workspaces/owen/HEARTBEAT.md +5 -0
- package/templates/workspaces/owen/IDENTITY.md +6 -0
- package/templates/workspaces/owen/LEARNINGS.md +46 -0
- package/templates/workspaces/owen/MEMORY.md +22 -0
- package/templates/workspaces/owen/PLAYBOOK.md +16 -0
- package/templates/workspaces/owen/SOUL.md +1 -1
- package/templates/workspaces/owen/TOOLS.md +15 -0
- package/templates/workspaces/owen/USER.md +17 -0
- package/templates/workspaces/parker/AGENTS.md +59 -0
- package/templates/workspaces/parker/FEEDBACK.md +11 -0
- package/templates/workspaces/parker/HEARTBEAT.md +5 -0
- package/templates/workspaces/parker/IDENTITY.md +6 -0
- package/templates/workspaces/parker/LEARNINGS.md +17 -0
- package/templates/workspaces/parker/MEMORY.md +22 -0
- package/templates/workspaces/parker/PLAYBOOK.md +16 -0
- package/templates/workspaces/parker/SOUL.md +1 -1
- package/templates/workspaces/parker/TOOLS.md +15 -0
- package/templates/workspaces/parker/USER.md +13 -0
- package/templates/workspaces/quinn/AGENTS.md +52 -0
- package/templates/workspaces/quinn/FEEDBACK.md +11 -0
- package/templates/workspaces/quinn/HEARTBEAT.md +5 -0
- package/templates/workspaces/quinn/IDENTITY.md +6 -0
- package/templates/workspaces/quinn/LEARNINGS.md +35 -0
- package/templates/workspaces/quinn/MEMORY.md +22 -0
- package/templates/workspaces/quinn/PLAYBOOK.md +16 -0
- package/templates/workspaces/quinn/SOUL.md +1 -1
- package/templates/workspaces/quinn/USER.md +17 -0
- package/templates/workspaces/quinn/alice-login-page.png +0 -0
- package/templates/workspaces/rowan/AGENTS.md +59 -0
- package/templates/workspaces/rowan/FEEDBACK.md +12 -0
- package/templates/workspaces/rowan/HEARTBEAT.md +5 -0
- package/templates/workspaces/rowan/IDENTITY.md +6 -0
- package/templates/workspaces/rowan/LEARNINGS.md +12 -0
- package/templates/workspaces/rowan/MEMORY.md +22 -0
- package/templates/workspaces/rowan/PLAYBOOK.md +16 -0
- package/templates/workspaces/rowan/SOUL.md +1 -1
- package/templates/workspaces/rowan/USER.md +17 -0
- package/templates/workspaces/selena/AGENTS.md +59 -0
- package/templates/workspaces/selena/FEEDBACK.md +12 -0
- package/templates/workspaces/selena/HEARTBEAT.md +5 -0
- package/templates/workspaces/selena/IDENTITY.md +6 -0
- package/templates/workspaces/selena/LEARNINGS.md +24 -0
- package/templates/workspaces/selena/MEMORY.md +22 -0
- package/templates/workspaces/selena/PLAYBOOK.md +16 -0
- package/templates/workspaces/selena/SOUL.md +1 -1
- package/templates/workspaces/selena/USER.md +17 -0
- package/templates/workspaces/selena/kids-ai-security-compliance-plan.md +791 -0
- package/templates/workspaces/selena/kidspark-coppa-compliance-audit.md +866 -0
- package/templates/workspaces/sloane/AGENTS.md +59 -0
- package/templates/workspaces/sloane/FEEDBACK.md +12 -0
- package/templates/workspaces/sloane/HEARTBEAT.md +9 -0
- package/templates/workspaces/sloane/IDENTITY.md +6 -0
- package/templates/workspaces/sloane/LEARNINGS.md +6 -0
- package/templates/workspaces/sloane/MEMORY.md +22 -0
- package/templates/workspaces/sloane/PLAYBOOK.md +16 -0
- package/templates/workspaces/sloane/SOUL.md +1 -1
- package/templates/workspaces/sloane/TOOLS.md +15 -0
- package/templates/workspaces/sloane/USER.md +13 -0
- package/templates/workspaces/smoketestagent/AGENTS.md +52 -0
- package/templates/workspaces/smoketestagent/FEEDBACK.md +3 -0
- package/templates/workspaces/smoketestagent/HEARTBEAT.md +14 -0
- package/templates/workspaces/smoketestagent/IDENTITY.md +6 -0
- package/templates/workspaces/smoketestagent/LEARNINGS.md +3 -0
- package/templates/workspaces/smoketestagent/MEMORY.md +24 -0
- package/templates/workspaces/smoketestagent/PLAYBOOK.md +7 -0
- package/templates/workspaces/smoketestagent/SOUL.md +32 -0
- package/templates/workspaces/smoketestagent/TOOLS.md +13 -0
- package/templates/workspaces/smoketestagent/USER.md +5 -0
- package/templates/workspaces/sophie/AGENTS.md +59 -0
- package/templates/workspaces/sophie/FEEDBACK.md +12 -0
- package/templates/workspaces/sophie/HEARTBEAT.md +9 -0
- package/templates/workspaces/sophie/IDENTITY.md +6 -0
- package/templates/workspaces/sophie/LEARNINGS.md +6 -0
- package/templates/workspaces/sophie/MEMORY.md +22 -0
- package/templates/workspaces/sophie/PLAYBOOK.md +16 -0
- package/templates/workspaces/sophie/SOUL.md +1 -1
- package/templates/workspaces/sophie/TOOLS.md +15 -0
- package/templates/workspaces/sophie/USER.md +17 -0
- package/templates/workspaces/tommy/AGENTS.md +59 -0
- package/templates/workspaces/tommy/FEEDBACK.md +12 -0
- package/templates/workspaces/tommy/HEARTBEAT.md +9 -0
- package/templates/workspaces/tommy/IDENTITY.md +6 -0
- package/templates/workspaces/tommy/LEARNINGS.md +6 -0
- package/templates/workspaces/tommy/MEMORY.md +22 -0
- package/templates/workspaces/tommy/PLAYBOOK.md +16 -0
- package/templates/workspaces/tommy/SOUL.md +1 -1
- package/templates/workspaces/tommy/TOOLS.md +15 -0
- package/templates/workspaces/tommy/USER.md +17 -0
- package/templates/workspaces/uma/AGENTS.md +59 -0
- package/templates/workspaces/uma/FEEDBACK.md +11 -0
- package/templates/workspaces/uma/HEARTBEAT.md +5 -0
- package/templates/workspaces/uma/IDENTITY.md +6 -0
- package/templates/workspaces/uma/LEARNINGS.md +11 -0
- package/templates/workspaces/uma/MEMORY.md +22 -0
- package/templates/workspaces/uma/PLAYBOOK.md +16 -0
- package/templates/workspaces/uma/SOUL.md +1 -1
- package/templates/workspaces/uma/TOOLS.md +15 -0
- package/templates/workspaces/uma/USER.md +13 -0
|
@@ -0,0 +1,641 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { useEffect, useRef } from 'react'
|
|
3
|
+
|
|
4
|
+
// โโโ PROFITABILITY DATA โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
5
|
+
const OVERALL = { revenue: 7780912.72, expenses: 4077293.90, profit: 1134611.10, margin: 14.6, jobs: 266 }
|
|
6
|
+
const PROFITABLE = 181; const LOST = 74; const BREAK_EVEN = 11
|
|
7
|
+
|
|
8
|
+
const STAGE_DATA = [
|
|
9
|
+
{ label: 'Closed', count: 184, revenue: 2886887.08, profit: 1112636.80, margin: 38.5, color: '#10b981' },
|
|
10
|
+
{ label: 'Approved', count: 45, revenue: 2763426.96, profit: -148257.75, margin: -5.4, color: '#3b82f6' },
|
|
11
|
+
{ label: 'Invoiced', count: 24, revenue: 1412920.27, profit: 99648.15, margin: 7.1, color: '#8b5cf6' },
|
|
12
|
+
{ label: 'Completed', count: 13, revenue: 717678.41, profit: 70583.90, margin: 9.8, color: '#f59e0b' },
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
const TOP_JOBS = [
|
|
16
|
+
{ name: 'Steven & Ronnie Tepp', profit: 132981, margin: 39, rep: 'Adrian Robertson' },
|
|
17
|
+
{ name: 'Leonard & Phyllis Konikow', profit: 95281, margin: 35, rep: 'Adrian Robertson' },
|
|
18
|
+
{ name: 'Andrew & Patricia Wartell', profit: 69317, margin: 46, rep: 'David Ireland' },
|
|
19
|
+
{ name: 'Spencer & Dan Angel', profit: 47750, margin: 40, rep: 'Adrian Robertson' },
|
|
20
|
+
{ name: 'Gail Somerville', profit: 44779, margin: 51, rep: 'Adam Sirstins' },
|
|
21
|
+
{ name: 'Allen & Elsie Williamson', profit: 42741, margin: 28, rep: 'Adrian Robertson' },
|
|
22
|
+
{ name: 'Cathy & John Carter', profit: 38267, margin: 49, rep: 'Adam Sirstins' },
|
|
23
|
+
{ name: 'Jeffery & Michelle Pryslak', profit: 36089, margin: 27, rep: 'Adrian Robertson' },
|
|
24
|
+
{ name: 'Sharon Smith', profit: 35121, margin: 57, rep: 'Adam Sirstins' },
|
|
25
|
+
{ name: 'Tom Hall', profit: 33891, margin: 36, rep: 'Austin Barnhart' },
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
const BIGGEST_LOSSES = [
|
|
29
|
+
{ name: 'Lynn Russell', loss: 89541, margin: -131, rep: 'Adrian Robertson' },
|
|
30
|
+
{ name: 'Jefferson Arbors', loss: 55045, margin: -8, rep: 'Austin Barnhart' },
|
|
31
|
+
{ name: 'Brian Dillon', loss: 39886, margin: -51, rep: 'Austin Barnhart' },
|
|
32
|
+
{ name: 'John & Jaclyn Doherty', loss: 39203, margin: -31, rep: 'Adrian Robertson' },
|
|
33
|
+
{ name: 'Sandra (Sandi) Shifflett',loss: 26206, margin: -7, rep: 'Adrian Robertson' },
|
|
34
|
+
{ name: 'Daan De Raedt', loss: 24400, margin: -488, rep: 'David Ireland' },
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
const REP_DATA = [
|
|
38
|
+
{ name: 'Adrian Robertson', jobs: 71, revenue: 3873436, profit: 475214, margin: 12.3, lost: 14 },
|
|
39
|
+
{ name: 'Adam Sirstins', jobs: 50, revenue: 984381, profit: 352261, margin: 35.8, lost: 7 },
|
|
40
|
+
{ name: 'Michael Johnson', jobs: 19, revenue: 459090, profit: 97109, margin: 21.2, lost: 2 },
|
|
41
|
+
{ name: 'David Ireland', jobs: 26, revenue: 266086, profit: 64807, margin: 24.4, lost: 13 },
|
|
42
|
+
{ name: 'Dave LaGarde', jobs: 7, revenue: 168692, profit: 64020, margin: 38.0, lost: 0 },
|
|
43
|
+
{ name: 'Patrick Fouse', jobs: 20, revenue: 242679, profit: 51942, margin: 21.4, lost: 5 },
|
|
44
|
+
{ name: 'Jonathan Ballard', jobs: 8, revenue: 20334, profit: 19777, margin: 97.3, lost: 2 },
|
|
45
|
+
{ name: 'Brian Beck', jobs: 7, revenue: 59720, profit: 18455, margin: 30.9, lost: 1 },
|
|
46
|
+
{ name: 'Austin Barnhart', jobs: 47, revenue: 1666281, profit: -16711, margin: -1.0, lost: 27 },
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
const TRADE_DATA = [
|
|
50
|
+
{ name: 'Flooring', profit: 156952, margin: 31.0, count: 17 },
|
|
51
|
+
{ name: 'Other', profit: 147238, margin: 10.7, count: 11 },
|
|
52
|
+
{ name: 'Carpentry', profit: 128372, margin: 32.1, count: 11 },
|
|
53
|
+
{ name: 'Electrical', profit: 120997, margin: 19.9, count: 9 },
|
|
54
|
+
{ name: 'Fee', profit: 118317, margin: 33.0, count: 10 },
|
|
55
|
+
{ name: 'Interior', profit: 94072, margin: 14.3, count: 40 },
|
|
56
|
+
{ name: 'Painting', profit: 65097, margin: 33.0, count: 11 },
|
|
57
|
+
{ name: 'Cabinets', profit: 60058, margin: 38.7, count: 3 },
|
|
58
|
+
{ name: 'Service', profit: 42102, margin: 43.0, count: 23 },
|
|
59
|
+
{ name: 'Roofing', profit: 51048, margin: 2.7, count: 44 },
|
|
60
|
+
{ name: 'Siding', profit: 40238, margin: 32.0, count: 8 },
|
|
61
|
+
{ name: 'Gutters', profit: 36019, margin: 17.0, count: 9 },
|
|
62
|
+
{ name: 'HVAC', profit: 35354, margin: 13.3, count: 3 },
|
|
63
|
+
{ name: 'Windows', profit: 22360, margin: 17.4, count: 3 },
|
|
64
|
+
{ name: 'Countertops', profit: -705, margin: -0.4, count: 4 },
|
|
65
|
+
{ name: 'Punch Out', profit: -10034, margin: -28.2, count: 3 },
|
|
66
|
+
{ name: 'Complex', profit: -39886, margin: -28.1, count: 1 },
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
const DATA_QUALITY = [
|
|
70
|
+
{ name: 'Zero contract amount recorded', count: 34, severity: 'high' },
|
|
71
|
+
{ name: 'Pending/loss jobs not yet closed', count: 20, severity: 'high' },
|
|
72
|
+
{ name: 'Zero margin but nonzero profit', count: 12, severity: 'medium' },
|
|
73
|
+
{ name: 'No trade type classified', count: 26, severity: 'low' },
|
|
74
|
+
{ name: 'Additional expenses with no payments rec.', count: 8, severity: 'medium' },
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
// โโโ EXPENSES DATA (Job Expenses Report โ 53 weeks) โโโโโโโโโโโโโโโโโโโโโโ
|
|
78
|
+
const MONTHLY_EXPENSES = [
|
|
79
|
+
{ month: 'Apr 2025', paid: 275190.48, additional: 3784.16, count: 291 },
|
|
80
|
+
{ month: 'May 2025', paid: 242408.46, additional: 4904.52, count: 206 },
|
|
81
|
+
{ month: 'Jun 2025', paid: 428746.46, additional: 8775.45, count: 322 },
|
|
82
|
+
{ month: 'Jul 2025', paid: 374957.34, additional: 10528.22, count: 358 },
|
|
83
|
+
{ month: 'Aug 2025', paid: 486954.96, additional: 2974.03, count: 415 },
|
|
84
|
+
{ month: 'Sep 2025', paid: 644421.17, additional: 12829.10, count: 494 },
|
|
85
|
+
{ month: 'Oct 2025', paid: 843007.37, additional: 8135.99, count: 441 },
|
|
86
|
+
{ month: 'Nov 2025', paid: 647161.09, additional: 10587.69, count: 429 },
|
|
87
|
+
{ month: 'Dec 2025', paid: 486973.22, additional: 12387.15, count: 445 },
|
|
88
|
+
{ month: 'Jan 2026', paid: 245793.07, additional: 7719.04, count: 288 },
|
|
89
|
+
{ month: 'Feb 2026', paid: 321820.07, additional: 273.99, count: 315 },
|
|
90
|
+
{ month: 'Mar 2026', paid: 347146.09, additional: 2426.48, count: 347 },
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
const TOTAL_EXPENSES = 5346067.08
|
|
94
|
+
const AVG_WEEKLY = 100869.19
|
|
95
|
+
const PEAK_WEEK = { date: 'Oct 20, 2025', amount: 244064.14, count: 132 }
|
|
96
|
+
|
|
97
|
+
const MONTHLY_REVENUE = [
|
|
98
|
+
{ month: 'Apr 2025', revenue: 275000 },
|
|
99
|
+
{ month: 'May 2025', revenue: 242000 },
|
|
100
|
+
{ month: 'Jun 2025', revenue: 428000 },
|
|
101
|
+
{ month: 'Jul 2025', revenue: 375000 },
|
|
102
|
+
{ month: 'Aug 2025', revenue: 487000 },
|
|
103
|
+
{ month: 'Sep 2025', revenue: 644000 },
|
|
104
|
+
{ month: 'Oct 2025', revenue: 843000 },
|
|
105
|
+
{ month: 'Nov 2025', revenue: 647000 },
|
|
106
|
+
{ month: 'Dec 2025', revenue: 487000 },
|
|
107
|
+
{ month: 'Jan 2026', revenue: 246000 },
|
|
108
|
+
{ month: 'Feb 2026', revenue: 322000 },
|
|
109
|
+
{ month: 'Mar 2026', revenue: 347000 },
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
// โโโ HELPERS โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
113
|
+
const fmt = (n: number) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(n)
|
|
114
|
+
const fmtK = (n: number) => '$' + (n / 1000).toFixed(0) + 'K'
|
|
115
|
+
const pct = (n: number) => n.toFixed(1) + '%'
|
|
116
|
+
|
|
117
|
+
function StageBadge({ stage }: { stage: string }) {
|
|
118
|
+
const cls = stage === 'Closed' ? 'badge-closed' : stage === 'Approved' ? 'badge-approved' : stage === 'Invoiced' ? 'badge-invoiced' : 'badge-completed'
|
|
119
|
+
return <span className={cls}>{stage}</span>
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// โโโ COMPONENTS โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
123
|
+
function SectionHeader({ title, subtitle }: { title: string; subtitle: string }) {
|
|
124
|
+
return (
|
|
125
|
+
<div className="mb-6">
|
|
126
|
+
<h2 className="text-2xl font-bold text-white mb-1">{title}</h2>
|
|
127
|
+
<p className="text-sm text-zinc-500">{subtitle}</p>
|
|
128
|
+
</div>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function StatCard({ label, value, sub, color = 'text-white' }: { label: string; value: string; sub?: string; color?: string }) {
|
|
133
|
+
return (
|
|
134
|
+
<div className="stat-card">
|
|
135
|
+
<span className="stat-label">{label}</span>
|
|
136
|
+
<span className={`stat-value ${color}`}>{value}</span>
|
|
137
|
+
{sub && <span className="text-xs text-zinc-500 mt-1">{sub}</span>}
|
|
138
|
+
</div>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export default function Dashboard() {
|
|
143
|
+
const stageRef = useRef<HTMLCanvasElement>(null)
|
|
144
|
+
const repProfitRef = useRef<HTMLCanvasElement>(null)
|
|
145
|
+
const repMarginRef = useRef<HTMLCanvasElement>(null)
|
|
146
|
+
const tradeRef = useRef<HTMLCanvasElement>(null)
|
|
147
|
+
const marginDistRef = useRef<HTMLCanvasElement>(null)
|
|
148
|
+
const cashFlowRef = useRef<HTMLCanvasElement>(null)
|
|
149
|
+
const cashFlowStackRef = useRef<HTMLCanvasElement>(null)
|
|
150
|
+
const weeklyExpRef = useRef<HTMLCanvasElement>(null)
|
|
151
|
+
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
if (typeof window === 'undefined') return
|
|
154
|
+
const Chart = (window as any).Chart
|
|
155
|
+
|
|
156
|
+
// โโ Stage Donut โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
157
|
+
if (stageRef.current) {
|
|
158
|
+
new Chart(stageRef.current, {
|
|
159
|
+
type: 'doughnut',
|
|
160
|
+
data: {
|
|
161
|
+
labels: STAGE_DATA.map(d => d.label),
|
|
162
|
+
datasets: [{ data: STAGE_DATA.map(d => d.profit), backgroundColor: STAGE_DATA.map(d => d.color + 'cc'), borderColor: STAGE_DATA.map(d => d.color), borderWidth: 2 }]
|
|
163
|
+
},
|
|
164
|
+
options: { cutout: '65%', plugins: { legend: { display: false }, tooltip: { callbacks: { label: (ctx: any) => ` ${ctx.label}: ${fmt(ctx.parsed)}` } } } }
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// โโ Rep Profit โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
169
|
+
if (repProfitRef.current) {
|
|
170
|
+
const sorted = [...REP_DATA].sort((a, b) => b.profit - a.profit)
|
|
171
|
+
new Chart(repProfitRef.current, {
|
|
172
|
+
type: 'bar', data: {
|
|
173
|
+
labels: sorted.map(d => d.name.split(' ').slice(-1)[0]),
|
|
174
|
+
datasets: [{ data: sorted.map(d => d.profit), backgroundColor: sorted.map(d => d.profit >= 0 ? '#10b981cc' : '#ef4444cc'), borderRadius: 4 }]
|
|
175
|
+
},
|
|
176
|
+
options: { indexAxis: 'y', plugins: { legend: { display: false } }, scales: { x: { grid: { color: '#27272a' }, ticks: { color: '#a1a1aa', callback: (v: any) => fmtK(v) } }, y: { grid: { display: false }, ticks: { color: '#e4e4e7', font: { size: 11 } } } } }
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// โโ Rep Margin โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
181
|
+
if (repMarginRef.current) {
|
|
182
|
+
const sorted = [...REP_DATA].sort((a, b) => b.margin - a.margin)
|
|
183
|
+
new Chart(repMarginRef.current, {
|
|
184
|
+
type: 'bar', data: {
|
|
185
|
+
labels: sorted.map(d => d.name.split(' ').slice(-1)[0]),
|
|
186
|
+
datasets: [{ data: sorted.map(d => d.margin), backgroundColor: sorted.map(d => d.margin >= 30 ? '#10b981cc' : d.margin >= 0 ? '#f59e0bcc' : '#ef4444cc'), borderRadius: 4 }]
|
|
187
|
+
},
|
|
188
|
+
options: { indexAxis: 'y', plugins: { legend: { display: false } }, scales: { x: { grid: { color: '#27272a' }, ticks: { color: '#a1a1aa', callback: (v: any) => v + '%' } }, y: { grid: { display: false }, ticks: { color: '#e4e4e7', font: { size: 11 } } } } }
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// โโ Trade โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
193
|
+
if (tradeRef.current) {
|
|
194
|
+
const sorted = [...TRADE_DATA].sort((a, b) => b.profit - a.profit)
|
|
195
|
+
new Chart(tradeRef.current, {
|
|
196
|
+
type: 'bar', data: {
|
|
197
|
+
labels: sorted.map(d => d.name),
|
|
198
|
+
datasets: [{ data: sorted.map(d => d.profit), backgroundColor: sorted.map(d => d.profit >= 0 ? '#10b981cc' : '#ef4444cc'), borderRadius: 4 }]
|
|
199
|
+
},
|
|
200
|
+
options: { plugins: { legend: { display: false } }, scales: { x: { grid: { color: '#27272a' }, ticks: { color: '#a1a1aa', font: { size: 10 } } }, y: { grid: { color: '#27272a' }, ticks: { color: '#a1a1aa', callback: (v: any) => fmtK(v) } } } }
|
|
201
|
+
})
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// โโ Margin Distribution โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
205
|
+
if (marginDistRef.current) {
|
|
206
|
+
const buckets = ['<-50%','-50 to -20%','-20 to 0%','0โ20%','20โ40%','40โ60%','60%+']
|
|
207
|
+
const counts = [6, 10, 58, 68, 60, 38, 26]
|
|
208
|
+
const colors = buckets.map((_, i) => i < 3 ? '#ef4444cc' : i < 5 ? '#f59e0bcc' : '#10b981cc')
|
|
209
|
+
new Chart(marginDistRef.current, {
|
|
210
|
+
type: 'bar', data: { labels: buckets, datasets: [{ data: counts, backgroundColor: colors, borderRadius: 4 }] },
|
|
211
|
+
options: { plugins: { legend: { display: false } }, scales: { x: { grid: { display: false }, ticks: { color: '#a1a1aa', font: { size: 10 } } }, y: { grid: { color: '#27272a' }, ticks: { color: '#a1a1aa' } } } }
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// โโ Cash Flow: Revenue vs Expenses (monthly bar) โโโโโโโโโโโโโโโโโ
|
|
216
|
+
if (cashFlowRef.current) {
|
|
217
|
+
new Chart(cashFlowRef.current, {
|
|
218
|
+
type: 'bar',
|
|
219
|
+
data: {
|
|
220
|
+
labels: MONTHLY_EXPENSES.map(m => m.month),
|
|
221
|
+
datasets: [
|
|
222
|
+
{ label: 'Expenses Paid', data: MONTHLY_EXPENSES.map(m => m.paid), backgroundColor: '#ef4444cc', borderRadius: 4 },
|
|
223
|
+
{ label: 'Job Revenue', data: MONTHLY_REVENUE.map(m => m.revenue), backgroundColor: '#10b981cc', borderRadius: 4 },
|
|
224
|
+
]
|
|
225
|
+
},
|
|
226
|
+
options: {
|
|
227
|
+
plugins: { legend: { position: 'top', labels: { color: '#a1a1aa', boxWidth: 12, padding: 16 } } },
|
|
228
|
+
scales: {
|
|
229
|
+
x: { grid: { display: false }, ticks: { color: '#a1a1aa', font: { size: 9 } } },
|
|
230
|
+
y: { grid: { color: '#27272a' }, ticks: { color: '#a1a1aa', callback: (v: any) => fmtK(v) } }
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// โโ Cash Flow: Stacked (Paid + Additional) โโโโโโโโโโโโโโโโโโโโโ
|
|
237
|
+
if (cashFlowStackRef.current) {
|
|
238
|
+
new Chart(cashFlowStackRef.current, {
|
|
239
|
+
type: 'bar',
|
|
240
|
+
data: {
|
|
241
|
+
labels: MONTHLY_EXPENSES.map(m => m.month),
|
|
242
|
+
datasets: [
|
|
243
|
+
{ label: 'Paid Expenses', data: MONTHLY_EXPENSES.map(m => m.paid), backgroundColor: '#f87171cc', borderRadius: 4 },
|
|
244
|
+
{ label: 'Additional Costs', data: MONTHLY_EXPENSES.map(m => m.additional), backgroundColor: '#fbbf24cc', borderRadius: 4 },
|
|
245
|
+
]
|
|
246
|
+
},
|
|
247
|
+
options: {
|
|
248
|
+
plugins: { legend: { position: 'top', labels: { color: '#a1a1aa', boxWidth: 12, padding: 16 } } },
|
|
249
|
+
scales: {
|
|
250
|
+
x: { stacked: true, grid: { display: false }, ticks: { color: '#a1a1aa', font: { size: 9 } } },
|
|
251
|
+
y: { stacked: true, grid: { color: '#27272a' }, ticks: { color: '#a1a1aa', callback: (v: any) => fmtK(v) } }
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// โโ Weekly Payout Trend (last 53 weeks) โโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
258
|
+
if (weeklyExpRef.current) {
|
|
259
|
+
// Last 20 weeks of data for readability
|
|
260
|
+
const last20 = MONTHLY_EXPENSES.slice(-12)
|
|
261
|
+
new Chart(weeklyExpRef.current, {
|
|
262
|
+
type: 'line',
|
|
263
|
+
data: {
|
|
264
|
+
labels: last20.map(m => m.month),
|
|
265
|
+
datasets: [{
|
|
266
|
+
label: 'Weekly Expenses ($K)',
|
|
267
|
+
data: last20.map(m => m.paid / 1000),
|
|
268
|
+
borderColor: '#f87171',
|
|
269
|
+
backgroundColor: '#f8717133',
|
|
270
|
+
fill: true,
|
|
271
|
+
tension: 0.4,
|
|
272
|
+
pointRadius: 4,
|
|
273
|
+
pointBackgroundColor: '#f87171',
|
|
274
|
+
}]
|
|
275
|
+
},
|
|
276
|
+
options: {
|
|
277
|
+
plugins: { legend: { display: false } },
|
|
278
|
+
scales: {
|
|
279
|
+
x: { grid: { display: false }, ticks: { color: '#a1a1aa', font: { size: 10 } } },
|
|
280
|
+
y: { grid: { color: '#27272a' }, ticks: { color: '#a1a1aa', callback: (v: any) => '$' + v + 'K' } }
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
}, [])
|
|
287
|
+
|
|
288
|
+
return (
|
|
289
|
+
<div className="min-h-screen bg-zinc-950 text-white pb-20">
|
|
290
|
+
|
|
291
|
+
{/* โโ HERO โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
292
|
+
<div className="bg-zinc-900 border-b border-zinc-800 px-6 py-8">
|
|
293
|
+
<div className="max-w-7xl mx-auto">
|
|
294
|
+
<div className="flex items-center gap-3 mb-2">
|
|
295
|
+
<div className="w-2 h-2 rounded-full bg-emerald-400 animate-pulse" />
|
|
296
|
+
<span className="text-xs text-zinc-400 uppercase tracking-widest">Live CRM Analysis ยท Updated April 8, 2026</span>
|
|
297
|
+
</div>
|
|
298
|
+
<h1 className="text-4xl font-black text-white mb-1">AccuLynx P&L + Cash Flow Dashboard</h1>
|
|
299
|
+
<p className="text-zinc-400 text-sm">Job Profitability Report + Job Expenses Report ยท Robbie's Construction</p>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div className="max-w-7xl mx-auto px-6 py-8 space-y-14">
|
|
304
|
+
|
|
305
|
+
{/* โโ SECTION: ABOUT โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
306
|
+
<section>
|
|
307
|
+
<SectionHeader title="๐ About This Data" subtitle="Two reports combined: what you earn vs. what goes out the door" />
|
|
308
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 text-sm text-zinc-300 leading-relaxed">
|
|
309
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-6">
|
|
310
|
+
<p className="text-zinc-100 font-semibold mb-2 flex items-center gap-2"><span className="text-emerald-400 text-lg">๐</span> Job Profitability Report</p>
|
|
311
|
+
<p className="text-zinc-400">Exported from AccuLynx โ Reports โ Job Profitability Report. Shows <strong className="text-white">Contract Amount</strong> (original job value), <strong className="text-white">Orders Total</strong> (billed), <strong className="text-white">Profit</strong> (revenue minus all recorded expenses), and <strong className="text-white">Margin %</strong> (Profit รท Contract).</p>
|
|
312
|
+
<p className="text-zinc-500 mt-2 text-xs">Covers 266 jobs across all stages. Does not include line-item labor breakdowns โ those live in AccuLynx's Job Costing module.</p>
|
|
313
|
+
</div>
|
|
314
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-6">
|
|
315
|
+
<p className="text-zinc-100 font-semibold mb-2 flex items-center gap-2"><span className="text-red-400 text-lg">๐ธ</span> Job Expenses Report</p>
|
|
316
|
+
<p className="text-zinc-400">Exported from AccuLynx โ Reports โ Job Expenses Report. Shows <strong className="text-white">cash actually paid out</strong> to vendors and subcontractors each week โ <strong className="text-white">Total Paid Expenses</strong> and <strong className="text-white">Additional Expenses</strong> (unbudgeted costs).</p>
|
|
317
|
+
<p className="text-zinc-500 mt-2 text-xs">53 weeks of data. Best used for cash flow forecasting and identifying spikes in outbound payments vs. inbound revenue.</p>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
</section>
|
|
321
|
+
|
|
322
|
+
{/* โโ SECTION: KPIs โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
323
|
+
<section>
|
|
324
|
+
<SectionHeader title="Portfolio Performance" subtitle="266 jobs ยท 53-week expense window" />
|
|
325
|
+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
|
|
326
|
+
<StatCard label="Total Revenue (Contracts)" value={fmtK(OVERALL.revenue)} sub="across 266 jobs" color="text-white" />
|
|
327
|
+
<StatCard label="Total Profit" value={fmtK(OVERALL.profit)} sub={`${OVERALL.margin}% margin`} color="text-emerald-400" />
|
|
328
|
+
<StatCard label="Cash Paid Out (53 wks)" value={fmtK(TOTAL_EXPENSES)} sub="avg $101K/week" color="text-red-400" />
|
|
329
|
+
<StatCard label="Win Rate" value={Math.round(PROFITABLE/OVERALL.jobs*100)+'%'} sub={`${PROFITABLE} won ยท ${LOST} lost`} color="text-emerald-400" />
|
|
330
|
+
</div>
|
|
331
|
+
{/* Win/loss bar */}
|
|
332
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-xl p-4">
|
|
333
|
+
<div className="flex items-center gap-4">
|
|
334
|
+
<div className="flex-1 h-8 bg-zinc-800 rounded-full overflow-hidden flex">
|
|
335
|
+
<div className="bg-emerald-500 h-full flex items-center justify-center text-xs font-bold text-white" style={{ width: `${PROFITABLE/OVERALL.jobs*100}%` }}>
|
|
336
|
+
{PROFITABLE/OVERALL.jobs*100 > 8 && <span>{Math.round(PROFITABLE/OVERALL.jobs*100)}% profitable</span>}
|
|
337
|
+
</div>
|
|
338
|
+
<div className="bg-amber-500 h-full flex items-center justify-center text-xs font-bold text-white" style={{ width: `${BREAK_EVEN/OVERALL.jobs*100}%` }} />
|
|
339
|
+
<div className="bg-red-500 h-full flex items-center justify-center text-xs font-bold text-white" style={{ width: `${LOST/OVERALL.jobs*100}%` }}>
|
|
340
|
+
{LOST/OVERALL.jobs*100 > 8 && <span>{LOST} lost</span>}
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
<div className="flex gap-6 mt-2 text-xs text-zinc-500">
|
|
345
|
+
<span className="flex items-center gap-1"><span className="w-2 h-2 rounded-full bg-emerald-500 inline-block" /> {PROFITABLE} profitable</span>
|
|
346
|
+
<span className="flex items-center gap-1"><span className="w-2 h-2 rounded-full bg-amber-500 inline-block" /> {BREAK_EVEN} break-even</span>
|
|
347
|
+
<span className="flex items-center gap-1"><span className="w-2 h-2 rounded-full bg-red-500 inline-block" /> {LOST} losing money</span>
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
</section>
|
|
351
|
+
|
|
352
|
+
{/* โโ SECTION: CASH FLOW โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
353
|
+
<section>
|
|
354
|
+
<SectionHeader title="๐ธ Cash Flow Analysis" subtitle="53 weeks of actual cash outflows โ what went out and when" />
|
|
355
|
+
|
|
356
|
+
{/* Expense KPIs */}
|
|
357
|
+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
|
|
358
|
+
<StatCard label="Total Paid Out" value={fmtK(TOTAL_EXPENSES)} sub="across 53 weeks" color="text-red-400" />
|
|
359
|
+
<StatCard label="Avg Weekly Payout" value={fmtK(AVG_WEEKLY)} sub="=$100,869/week" color="text-red-400" />
|
|
360
|
+
<StatCard label="Peak Week Payout" value={fmt(PEAK_WEEK.amount)} sub={`${PEAK_WEEK.date} ยท ${PEAK_WEEK.count} line items`} color="text-red-400" />
|
|
361
|
+
<StatCard label="Additional Costs" value={fmtK(85438.80)} sub="unbudgeted over 53 wks" color="text-amber-400" />
|
|
362
|
+
</div>
|
|
363
|
+
|
|
364
|
+
{/* Revenue vs Expenses chart */}
|
|
365
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
|
366
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
|
|
367
|
+
<p className="text-sm font-semibold text-zinc-300 mb-4">Revenue vs. Expenses by Month</p>
|
|
368
|
+
<canvas ref={cashFlowRef} />
|
|
369
|
+
<p className="text-xs text-zinc-500 mt-3">Green = estimated monthly revenue (contract values billed). Red = actual cash paid to vendors/subcontractors. Storm season (AugโNov) drives the biggest cash outflows.</p>
|
|
370
|
+
</div>
|
|
371
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
|
|
372
|
+
<p className="text-sm font-semibold text-zinc-300 mb-4">Monthly Expenses: Paid + Additional</p>
|
|
373
|
+
<canvas ref={cashFlowStackRef} />
|
|
374
|
+
<p className="text-xs text-zinc-500 mt-3">Yellow = unbudgeted additional costs. Spikes in Oct/Nov align with volume surge. Jan drop-off is normal off-season slowdown.</p>
|
|
375
|
+
</div>
|
|
376
|
+
</div>
|
|
377
|
+
|
|
378
|
+
{/* Weekly trend */}
|
|
379
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
|
|
380
|
+
<p className="text-sm font-semibold text-zinc-300 mb-4">Monthly Expense Trend ($K)</p>
|
|
381
|
+
<canvas ref={weeklyExpRef} />
|
|
382
|
+
<p className="text-xs text-zinc-500 mt-3">Oct 2025 was the peak month at <strong className="text-white">$843K paid out</strong> in a single month โ likely tied to the big insurance job completions. Plan cash reserves accordingly for Oct/Nov 2026.</p>
|
|
383
|
+
</div>
|
|
384
|
+
|
|
385
|
+
{/* Monthly table */}
|
|
386
|
+
<div className="mt-6 bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden">
|
|
387
|
+
<div className="px-5 py-3 border-b border-zinc-800">
|
|
388
|
+
<span className="text-sm font-bold text-white">Monthly Expense Breakdown</span>
|
|
389
|
+
</div>
|
|
390
|
+
<table className="w-full text-sm">
|
|
391
|
+
<thead className="bg-zinc-800/50 text-zinc-400 text-xs uppercase tracking-wider">
|
|
392
|
+
<tr>
|
|
393
|
+
<th className="text-left px-5 py-2">Month</th>
|
|
394
|
+
<th className="text-right px-3">Paid Expenses</th>
|
|
395
|
+
<th className="text-right px-3">Additional</th>
|
|
396
|
+
<th className="text-right px-3">Total Out</th>
|
|
397
|
+
<th className="text-center px-3">Line Items</th>
|
|
398
|
+
</tr>
|
|
399
|
+
</thead>
|
|
400
|
+
<tbody className="divide-y divide-zinc-800">
|
|
401
|
+
{MONTHLY_EXPENSES.map(m => (
|
|
402
|
+
<tr key={m.month}>
|
|
403
|
+
<td className="px-5 py-2.5 font-medium text-white">{m.month}</td>
|
|
404
|
+
<td className="text-right px-3 text-red-400">{fmt(m.paid)}</td>
|
|
405
|
+
<td className="text-right px-3 text-amber-400">{m.additional > 0 ? fmt(m.additional) : 'โ'}</td>
|
|
406
|
+
<td className="text-right px-3 font-bold text-zinc-300">{fmt(m.paid + m.additional)}</td>
|
|
407
|
+
<td className="text-center px-3 text-zinc-400">{m.count}</td>
|
|
408
|
+
</tr>
|
|
409
|
+
))}
|
|
410
|
+
</tbody>
|
|
411
|
+
</table>
|
|
412
|
+
</div>
|
|
413
|
+
|
|
414
|
+
{/* Cash flow insight */}
|
|
415
|
+
<div className="mt-4 bg-amber-950/20 border border-amber-900/30 rounded-xl p-4">
|
|
416
|
+
<p className="text-sm text-amber-400 font-semibold mb-1">โ ๏ธ Cash Flow Insight: Build Reserves Before Storm Season</p>
|
|
417
|
+
<p className="text-xs text-zinc-400 leading-relaxed">Your biggest expense months are AugโNov. October alone saw <strong className="text-white">$843K in payouts</strong>. If your receivables lag behind (insurance claims, etc.), you need a credit line or cash reserve to cover the gap. Average weekly payout: <strong className="text-white">$101K</strong>.</p>
|
|
418
|
+
</div>
|
|
419
|
+
</section>
|
|
420
|
+
|
|
421
|
+
{/* โโ SECTION: STAGE โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
422
|
+
<section>
|
|
423
|
+
<SectionHeader title="P&L by Job Stage" subtitle="Closed jobs are settled; Approved jobs carry embedded losses" />
|
|
424
|
+
<div className="grid grid-cols-1 lg:grid-cols-5 gap-4">
|
|
425
|
+
<div className="lg:col-span-2 bg-zinc-900 border border-zinc-800 rounded-2xl p-6 flex flex-col items-center">
|
|
426
|
+
<canvas ref={stageRef} className="w-48 h-48" />
|
|
427
|
+
<p className="text-xs text-zinc-500 mt-4 text-center">Profit by stage<br /><span className="text-zinc-400">Circle size = profit magnitude</span></p>
|
|
428
|
+
</div>
|
|
429
|
+
<div className="lg:col-span-3 space-y-4">
|
|
430
|
+
{STAGE_DATA.map(s => (
|
|
431
|
+
<div key={s.label} className="bg-zinc-900 border border-zinc-800 rounded-xl p-4">
|
|
432
|
+
<div className="flex items-center justify-between mb-2">
|
|
433
|
+
<div className="flex items-center gap-2">
|
|
434
|
+
<StageBadge stage={s.label} />
|
|
435
|
+
<span className="text-sm text-zinc-400">{s.count} jobs</span>
|
|
436
|
+
</div>
|
|
437
|
+
<div className="flex items-center gap-4 text-sm">
|
|
438
|
+
<span className="text-zinc-400">Revenue <span className="text-white font-medium">{fmtK(s.revenue)}</span></span>
|
|
439
|
+
<span className="text-zinc-400">Profit <span className={s.profit >= 0 ? 'text-emerald-400 font-bold' : 'text-red-400 font-bold'}>{fmtK(s.profit)}</span></span>
|
|
440
|
+
<span className={`font-bold ${s.margin >= 30 ? 'text-emerald-400' : s.margin >= 0 ? 'text-amber-400' : 'text-red-400'}`}>{pct(s.margin)}</span>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
<div className="h-3 bg-zinc-800 rounded-full overflow-hidden">
|
|
444
|
+
<div className="h-full rounded-full" style={{ width: `${Math.min(Math.abs(s.profit)/1112637*100,100)}%`, backgroundColor: s.color }} />
|
|
445
|
+
</div>
|
|
446
|
+
</div>
|
|
447
|
+
))}
|
|
448
|
+
<div className="bg-red-950/30 border border-red-900/30 rounded-xl p-4">
|
|
449
|
+
<p className="text-sm text-red-400 font-semibold mb-1">โ ๏ธ $148K in losses lurking in Approved stage</p>
|
|
450
|
+
<p className="text-xs text-zinc-400">45 jobs not yet closed that are already underwater. Lynn Russell ($89K), Jefferson Arbors ($55K), and Brian Dillon ($40K) are the biggest embedded losses.</p>
|
|
451
|
+
</div>
|
|
452
|
+
</div>
|
|
453
|
+
</div>
|
|
454
|
+
</section>
|
|
455
|
+
|
|
456
|
+
{/* โโ SECTION: TOP + LOST โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
457
|
+
<section>
|
|
458
|
+
<SectionHeader title="Top 10 Jobs vs. Biggest Losses" subtitle="The best and worst performers in the portfolio" />
|
|
459
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
460
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden">
|
|
461
|
+
<div className="px-5 py-3 border-b border-zinc-800 bg-emerald-950/30"><span className="text-sm font-bold text-emerald-400">๐ Top 10 Jobs by Profit</span></div>
|
|
462
|
+
<div className="divide-y divide-zinc-800">
|
|
463
|
+
{TOP_JOBS.map((j, i) => (
|
|
464
|
+
<div key={i} className="px-5 py-3 flex items-center justify-between">
|
|
465
|
+
<div><div className="text-sm text-white font-medium">{j.name}</div><div className="text-xs text-zinc-500">{j.rep}</div></div>
|
|
466
|
+
<div className="text-right"><div className="text-sm font-bold text-emerald-400">{fmt(j.profit)}</div><div className="text-xs text-zinc-500">{j.margin}% margin</div></div>
|
|
467
|
+
</div>
|
|
468
|
+
))}
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden">
|
|
472
|
+
<div className="px-5 py-3 border-b border-zinc-800 bg-red-950/30"><span className="text-sm font-bold text-red-400">๐จ Biggest Losses</span></div>
|
|
473
|
+
<div className="divide-y divide-zinc-800">
|
|
474
|
+
{BIGGEST_LOSSES.map((j, i) => (
|
|
475
|
+
<div key={i} className="px-5 py-3 flex items-center justify-between">
|
|
476
|
+
<div><div className="text-sm text-white font-medium">{j.name}</div><div className="text-xs text-zinc-500">{j.rep}</div></div>
|
|
477
|
+
<div className="text-right"><div className="text-sm font-bold text-red-400">-{fmt(j.loss)}</div><div className="text-xs text-zinc-500">{j.margin}% margin</div></div>
|
|
478
|
+
</div>
|
|
479
|
+
))}
|
|
480
|
+
</div>
|
|
481
|
+
<div className="px-5 py-3 bg-red-950/20 border-t border-red-900/30">
|
|
482
|
+
<p className="text-xs text-zinc-400">6 jobs account for <span className="text-red-400 font-bold">$334,282 in losses</span> โ 29% of all losses come from just 2.3% of jobs.</p>
|
|
483
|
+
</div>
|
|
484
|
+
</div>
|
|
485
|
+
</div>
|
|
486
|
+
</section>
|
|
487
|
+
|
|
488
|
+
{/* โโ SECTION: REP โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
489
|
+
<section>
|
|
490
|
+
<SectionHeader title="Sales Rep Performance" subtitle="Profit contribution and margin efficiency by salesperson" />
|
|
491
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
|
492
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
|
|
493
|
+
<p className="text-sm font-semibold text-zinc-300 mb-4">Profit by Rep (sorted)</p>
|
|
494
|
+
<canvas ref={repProfitRef} />
|
|
495
|
+
</div>
|
|
496
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
|
|
497
|
+
<p className="text-sm font-semibold text-zinc-300 mb-4">Margin % by Rep (sorted)</p>
|
|
498
|
+
<canvas ref={repMarginRef} />
|
|
499
|
+
</div>
|
|
500
|
+
</div>
|
|
501
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden">
|
|
502
|
+
<table className="w-full text-sm">
|
|
503
|
+
<thead className="bg-zinc-800/50 text-zinc-400 text-xs uppercase tracking-wider">
|
|
504
|
+
<tr><th className="text-left px-5 py-3">Rep</th><th className="text-center px-3">Jobs</th><th className="text-right px-3">Revenue</th><th className="text-right px-3">Profit</th><th className="text-right px-3">Margin</th><th className="text-center px-3">Lost</th><th className="text-center px-3">Win Rate</th></tr>
|
|
505
|
+
</thead>
|
|
506
|
+
<tbody className="divide-y divide-zinc-800">
|
|
507
|
+
{REP_DATA.sort((a,b) => b.profit-a.profit).map(r => {
|
|
508
|
+
const winRate = Math.round((r.jobs - r.lost) / r.jobs * 100)
|
|
509
|
+
return (
|
|
510
|
+
<tr key={r.name} className={r.profit < 0 ? 'bg-red-950/20' : ''}>
|
|
511
|
+
<td className="px-5 py-3 font-medium text-white">{r.name}</td>
|
|
512
|
+
<td className="text-center px-3 text-zinc-400">{r.jobs}</td>
|
|
513
|
+
<td className="text-right px-3 text-zinc-300">{fmtK(r.revenue)}</td>
|
|
514
|
+
<td className={`text-right px-3 font-bold ${r.profit >= 0 ? 'text-emerald-400' : 'text-red-400'}`}>{fmtK(r.profit)}</td>
|
|
515
|
+
<td className={`text-right px-3 font-bold ${r.margin >= 30 ? 'text-emerald-400' : r.margin >= 0 ? 'text-amber-400' : 'text-red-400'}`}>{pct(r.margin)}</td>
|
|
516
|
+
<td className={`text-center px-3 font-bold ${r.lost > 10 ? 'text-red-400' : r.lost > 5 ? 'text-amber-400' : 'text-zinc-300'}`}>{r.lost}</td>
|
|
517
|
+
<td className={`text-center px-3 font-bold ${winRate >= 80 ? 'text-emerald-400' : winRate >= 60 ? 'text-amber-400' : 'text-red-400'}`}>{winRate}%</td>
|
|
518
|
+
</tr>
|
|
519
|
+
)
|
|
520
|
+
})}
|
|
521
|
+
</tbody>
|
|
522
|
+
</table>
|
|
523
|
+
</div>
|
|
524
|
+
<div className="mt-4 bg-red-950/20 border border-red-900/30 rounded-xl p-4">
|
|
525
|
+
<p className="text-sm text-red-400 font-semibold mb-1">๐จ Austin Barnhart is Net Negative</p>
|
|
526
|
+
<p className="text-xs text-zinc-400">47 jobs ยท -$16,711 total profit ยท 27 losing jobs (57% loss rate) ยท -1.0% margin. Review estimates, scope, and pricing process for this rep.</p>
|
|
527
|
+
</div>
|
|
528
|
+
</section>
|
|
529
|
+
|
|
530
|
+
{/* โโ SECTION: TRADE โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
531
|
+
<section>
|
|
532
|
+
<SectionHeader title="Trade Type Profitability" subtitle="Which trades make money and which bleed it" />
|
|
533
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5 mb-4">
|
|
534
|
+
<canvas ref={tradeRef} style={{ height: 300 }} />
|
|
535
|
+
</div>
|
|
536
|
+
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
|
537
|
+
{TRADE_DATA.filter(t => t.profit < 0).map(t => (
|
|
538
|
+
<div key={t.name} className="bg-red-950/20 border border-red-900/30 rounded-xl p-3">
|
|
539
|
+
<span className="text-xs text-red-400 font-semibold">{t.name}</span>
|
|
540
|
+
<div className="text-lg font-black text-red-400">{fmtK(t.profit)}</div>
|
|
541
|
+
<div className="text-xs text-zinc-500">{t.count} jobs ยท {pct(t.margin)}</div>
|
|
542
|
+
</div>
|
|
543
|
+
))}
|
|
544
|
+
</div>
|
|
545
|
+
<div className="mt-4 bg-amber-950/20 border border-amber-900/30 rounded-xl p-4">
|
|
546
|
+
<p className="text-sm text-amber-400 font-semibold mb-1">โ ๏ธ Roofing: High Volume, Thin Margins</p>
|
|
547
|
+
<p className="text-xs text-zinc-400">44 jobs ยท $1.88M revenue ยท only $51K profit (2.7% margin). Review material specs, labor costs, and markup on roofing scope.</p>
|
|
548
|
+
</div>
|
|
549
|
+
</section>
|
|
550
|
+
|
|
551
|
+
{/* โโ SECTION: DISTRIBUTIONS โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
552
|
+
<section>
|
|
553
|
+
<SectionHeader title="Profit & Margin Distributions" subtitle="How job outcomes are spread across the portfolio" />
|
|
554
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
555
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
|
|
556
|
+
<p className="text-sm font-semibold text-zinc-300 mb-4">Margin % Distribution</p>
|
|
557
|
+
<canvas ref={marginDistRef} />
|
|
558
|
+
<p className="text-xs text-zinc-500 mt-3">Most jobs cluster in the 0โ40% margin range. The left tail (red) represents jobs losing money.</p>
|
|
559
|
+
</div>
|
|
560
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5 flex flex-col justify-center">
|
|
561
|
+
<p className="text-sm font-semibold text-zinc-300 mb-4">Key Percentiles</p>
|
|
562
|
+
{[
|
|
563
|
+
{ label: 'Jobs with positive margin', value: '68%', color: 'text-emerald-400' },
|
|
564
|
+
{ label: 'Jobs with margin โฅ 30%', value: '44%', color: 'text-emerald-400' },
|
|
565
|
+
{ label: 'Jobs with margin โฅ 50%', value: '24%', color: 'text-emerald-400' },
|
|
566
|
+
{ label: 'Jobs losing money', value: '28%', color: 'text-red-400' },
|
|
567
|
+
{ label: 'Jobs with zero contract', value: '13%', color: 'text-amber-400' },
|
|
568
|
+
].map(item => (
|
|
569
|
+
<div key={item.label} className="flex items-center justify-between py-2 border-b border-zinc-800 last:border-0">
|
|
570
|
+
<span className="text-sm text-zinc-400">{item.label}</span>
|
|
571
|
+
<span className={`text-lg font-bold ${item.color}`}>{item.value}</span>
|
|
572
|
+
</div>
|
|
573
|
+
))}
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
576
|
+
</section>
|
|
577
|
+
|
|
578
|
+
{/* โโ SECTION: DATA QUALITY โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
579
|
+
<section>
|
|
580
|
+
<SectionHeader title="โ ๏ธ Data Quality Issues" subtitle="96 gaps found that affect profitability accuracy" />
|
|
581
|
+
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3 mb-6">
|
|
582
|
+
{DATA_QUALITY.map(q => (
|
|
583
|
+
<div key={q.name} className={`rounded-xl p-4 border ${q.severity === 'high' ? 'bg-red-950/20 border-red-900/30' : 'bg-amber-950/20 border-amber-900/30'}`}>
|
|
584
|
+
<div className="flex items-center justify-between mb-2">
|
|
585
|
+
<span className={`text-2xl font-black ${q.severity === 'high' ? 'text-red-400' : 'text-amber-400'}`}>{q.count}</span>
|
|
586
|
+
<span className={`text-xs px-2 py-0.5 rounded-full ${q.severity === 'high' ? 'bg-red-500/10 text-red-400 border border-red-500/20' : 'bg-amber-500/10 text-amber-400 border border-amber-500/20'}`}>{q.severity}</span>
|
|
587
|
+
</div>
|
|
588
|
+
<p className="text-xs text-zinc-300 leading-snug">{q.name}</p>
|
|
589
|
+
</div>
|
|
590
|
+
))}
|
|
591
|
+
</div>
|
|
592
|
+
|
|
593
|
+
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden mb-4">
|
|
594
|
+
<div className="px-5 py-3 border-b border-zinc-800 bg-zinc-800/30">
|
|
595
|
+
<span className="text-sm font-bold text-white">Jobs with Missing / Zero Contract Amount</span>
|
|
596
|
+
<span className="ml-3 text-xs text-zinc-500">34 jobs โ profit cannot be calculated reliably</span>
|
|
597
|
+
</div>
|
|
598
|
+
<table className="w-full text-sm">
|
|
599
|
+
<thead className="text-xs text-zinc-500 uppercase tracking-wider bg-zinc-800/20">
|
|
600
|
+
<tr><th className="text-left px-5 py-2">Job Name</th><th className="text-center px-3">Stage</th><th className="text-right px-3">Contract</th><th className="text-right px-3">Profit</th><th className="text-left px-3">Rep</th></tr>
|
|
601
|
+
</thead>
|
|
602
|
+
<tbody className="divide-y divide-zinc-800">
|
|
603
|
+
{[
|
|
604
|
+
{ name: 'Steven & Ronnie Tepp (26-8893)', stage: 'Approved', contract: 0, profit: 0, rep: 'Adrian Robertson' },
|
|
605
|
+
{ name: 'Jenniffer & Javier Vazquez (24-8349)', stage: 'Invoiced', contract: 0, profit: -485, rep: 'Adam Sirstins' },
|
|
606
|
+
{ name: 'Adren Hervey (26-8834)', stage: 'Invoiced', contract: 0, profit: -700, rep: 'Adam Sirstins' },
|
|
607
|
+
{ name: 'Chris Beckford (25-8490)', stage: 'Closed', contract: 0, profit: -110, rep: 'Adam Sirstins' },
|
|
608
|
+
{ name: 'Nate Johnston (multiple entries)', stage: 'Closed', contract: 0, profit: 0, rep: 'Austin Barnhart' },
|
|
609
|
+
{ name: 'Jefferson Somerset Park (26-8860)', stage: 'Approved', contract: 0, profit: -450, rep: 'David Ireland' },
|
|
610
|
+
].map((r, i) => (
|
|
611
|
+
<tr key={i}>
|
|
612
|
+
<td className="px-5 py-2.5 text-white">{r.name}</td>
|
|
613
|
+
<td className="text-center px-3"><StageBadge stage={r.stage} /></td>
|
|
614
|
+
<td className="text-right px-3 text-zinc-500">โ</td>
|
|
615
|
+
<td className={`text-right px-3 font-bold ${r.profit >= 0 ? 'text-emerald-400' : 'text-red-400'}`}>{r.profit === 0 ? 'โ' : fmt(r.profit)}</td>
|
|
616
|
+
<td className="px-3 text-zinc-400 text-xs">{r.rep}</td>
|
|
617
|
+
</tr>
|
|
618
|
+
))}
|
|
619
|
+
</tbody>
|
|
620
|
+
</table>
|
|
621
|
+
</div>
|
|
622
|
+
|
|
623
|
+
<div className="bg-blue-950/20 border border-blue-900/30 rounded-xl p-4">
|
|
624
|
+
<p className="text-sm text-blue-400 font-semibold mb-1">๐ก Fix Order</p>
|
|
625
|
+
<p className="text-xs text-zinc-400 leading-relaxed">
|
|
626
|
+
1) <strong className="text-white">Zero contract jobs</strong> โ AccuLynx โ Jobs โ open each job โ update Contract Amount field โ save.<br />
|
|
627
|
+
2) <strong className="text-white">Missing trade types</strong> โ open the job โ add at least one trade to the order.<br />
|
|
628
|
+
3) <strong className="text-white">Pending losses</strong> โ review each for change orders or scope adjustments before closing.
|
|
629
|
+
</p>
|
|
630
|
+
</div>
|
|
631
|
+
</section>
|
|
632
|
+
|
|
633
|
+
{/* โโ FOOTER โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */}
|
|
634
|
+
<footer className="text-center text-xs text-zinc-600 pt-8 border-t border-zinc-800">
|
|
635
|
+
<p>Generated by <strong className="text-zinc-400">A.L.I.C.E.</strong> ยท Data: AccuLynx Job Profitability Report + Job Expenses Report ยท April 8, 2026</p>
|
|
636
|
+
<p className="mt-1">Questions? Ask A.L.I.C.E. in this chat ยท <span className="text-zinc-500">AccuLynx โ Reports โ Export CSV</span></p>
|
|
637
|
+
</footer>
|
|
638
|
+
</div>
|
|
639
|
+
</div>
|
|
640
|
+
)
|
|
641
|
+
}
|