demo bug fixes
This commit is contained in:
@@ -112,8 +112,7 @@ const Layout = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Determine standard layout vs full screen for Public pages
|
// Determine standard layout vs full screen for Public pages
|
||||||
const isPublic = ['/', '/login', '/estimate'].includes(location.pathname)
|
const isPublic = ['/', '/login'].includes(location.pathname);
|
||||||
|| location.pathname.startsWith('/ads/');
|
|
||||||
|
|
||||||
if (isPublic) {
|
if (isPublic) {
|
||||||
return (
|
return (
|
||||||
@@ -155,12 +154,12 @@ const Layout = () => {
|
|||||||
{ to: "/admin/schedule", icon: Calendar, label: "Team Schedule" },
|
{ to: "/admin/schedule", icon: Calendar, label: "Team Schedule" },
|
||||||
{ to: "/admin/leaderboard", icon: Trophy, label: "Leaderboard" },
|
{ to: "/admin/leaderboard", icon: Trophy, label: "Leaderboard" },
|
||||||
{ to: "/owner/subcontractor-tasks", icon: HardHat, label: "Subcontractor Tasks" },
|
{ to: "/owner/subcontractor-tasks", icon: HardHat, label: "Subcontractor Tasks" },
|
||||||
{ to: "/owner/payments", icon: CreditCard, label: "Payment Management" },
|
|
||||||
{ to: "/owner/people", icon: Users, label: "People" },
|
{ to: "/owner/people", icon: Users, label: "People" },
|
||||||
{ to: "/owner/settings", icon: Settings, label: "Org Settings" },
|
{ to: "/owner/settings", icon: Settings, label: "Org Settings" },
|
||||||
...commonItems,
|
...commonItems,
|
||||||
{ to: "/estimate-wizard/admin", icon: Settings, label: "Wizard Admin" },
|
{ to: "/estimate-wizard/admin", icon: Settings, label: "Wizard Admin" },
|
||||||
{ to: "/marketing", icon: Megaphone, label: "Ad Engine" },
|
{ to: "/marketing", icon: Megaphone, label: "Ad Engine" },
|
||||||
|
{ to: "/owner/payments", icon: CreditCard, label: "Manage Payments" },
|
||||||
{ type: "section", label: "Upcoming Features" },
|
{ type: "section", label: "Upcoming Features" },
|
||||||
{ to: "/campaignx", icon: Rocket, label: <span>Campaign<span className="text-amber-500">X</span></span> },
|
{ to: "/campaignx", icon: Rocket, label: <span>Campaign<span className="text-amber-500">X</span></span> },
|
||||||
];
|
];
|
||||||
@@ -182,11 +181,11 @@ const Layout = () => {
|
|||||||
},
|
},
|
||||||
{ to: "/admin/estimates", icon: Calculator, label: "Estimates" },
|
{ to: "/admin/estimates", icon: Calculator, label: "Estimates" },
|
||||||
{ to: "/admin/subcontractor-tasks", icon: HardHat, label: "Subcontractor Tasks" },
|
{ to: "/admin/subcontractor-tasks", icon: HardHat, label: "Subcontractor Tasks" },
|
||||||
{ to: "/owner/payments", icon: CreditCard, label: "Payment Management" },
|
|
||||||
{ to: "/admin/settings", icon: Settings, label: "Org Settings" },
|
{ to: "/admin/settings", icon: Settings, label: "Org Settings" },
|
||||||
...commonItems,
|
...commonItems,
|
||||||
{ to: "/estimate-wizard/admin", icon: Settings, label: "Wizard Admin" },
|
{ to: "/estimate-wizard/admin", icon: Settings, label: "Wizard Admin" },
|
||||||
{ to: "/marketing", icon: Megaphone, label: "Ad Engine" },
|
{ to: "/marketing", icon: Megaphone, label: "Ad Engine" },
|
||||||
|
{ to: "/owner/payments", icon: CreditCard, label: "Manage Payments" },
|
||||||
{ type: "section", label: "Upcoming Features" },
|
{ type: "section", label: "Upcoming Features" },
|
||||||
{ to: "/campaignx", icon: Rocket, label: <span>Campaign<span className="text-amber-500">X</span></span> },
|
{ to: "/campaignx", icon: Rocket, label: <span>Campaign<span className="text-amber-500">X</span></span> },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -9,12 +9,8 @@ export const ThemeProvider = ({ children }) => {
|
|||||||
if (savedTheme) {
|
if (savedTheme) {
|
||||||
return savedTheme;
|
return savedTheme;
|
||||||
}
|
}
|
||||||
// Check system preference
|
|
||||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
||||||
return 'dark';
|
|
||||||
}
|
}
|
||||||
}
|
return 'dark'; // Default to dark for first-time visitors
|
||||||
return 'light'; // Default to light if no preference
|
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
+21
-5
@@ -3613,9 +3613,9 @@ const MOCK_PROJECTS = [
|
|||||||
budget: 19600,
|
budget: 19600,
|
||||||
approvedBudget: 19600,
|
approvedBudget: 19600,
|
||||||
committedCost: 18100,
|
committedCost: 18100,
|
||||||
actualCost: 0,
|
actualCost: 18100,
|
||||||
spent: 0,
|
spent: 18100,
|
||||||
variancePercent: -100.0,
|
variancePercent: -7.7,
|
||||||
margin: 0.08,
|
margin: 0.08,
|
||||||
commissionType: 'percent_gross',
|
commissionType: 'percent_gross',
|
||||||
commissionRate: 10,
|
commissionRate: 10,
|
||||||
@@ -3632,6 +3632,22 @@ const MOCK_PROJECTS = [
|
|||||||
{ name: 'City of Plano', category: 'Permits', allocated: 600, committed: 600, actual: 0 },
|
{ name: 'City of Plano', category: 'Permits', allocated: 600, committed: 600, actual: 0 },
|
||||||
{ name: 'Reserve Fund', category: 'Contingency', allocated: 1500, committed: 0, actual: 0 },
|
{ name: 'Reserve Fund', category: 'Contingency', allocated: 1500, committed: 0, actual: 0 },
|
||||||
],
|
],
|
||||||
|
expenses: [
|
||||||
|
{ id: 'exp_017_1', type: 'material', name: 'Owens Corning', category: 'Materials', allocated: 10500, actual: 10500, paid: true, paymentRequests: [
|
||||||
|
{ id: 'req_017_1_1', requestDate: '2026-04-02', requestedAmount: 10500, amountPaid: 10500, paymentDate: '2026-04-04' }
|
||||||
|
] },
|
||||||
|
{ id: 'exp_017_2', type: 'labor', name: 'Plano Roofing Crew C', category: 'Labor', allocated: 7000, actual: 7000, paid: true, paymentRequests: [
|
||||||
|
{ id: 'req_017_2_1', requestDate: '2026-04-22', requestedAmount: 7000, amountPaid: 7000, paymentDate: '2026-04-24' }
|
||||||
|
] },
|
||||||
|
{ id: 'exp_017_3', type: 'other', name: 'City of Plano', category: 'Permits', allocated: 600, actual: 600, paid: true, paymentRequests: [
|
||||||
|
{ id: 'req_017_3_1', requestDate: '2026-04-10', requestedAmount: 600, amountPaid: 600, paymentDate: '2026-04-10' }
|
||||||
|
] }
|
||||||
|
],
|
||||||
|
paymentsReceived: [
|
||||||
|
{ id: 'rcv_017_1', from: 'Adriana Voss', method: 'Check', amount: 5880, date: '2026-03-28', refNumber: 'CHK-2017-01', memo: 'Deposit — 30%' },
|
||||||
|
{ id: 'rcv_017_2', from: 'Farmers Insurance', method: 'ACH', amount: 7840, date: '2026-04-25', refNumber: 'ACH-2017-02', memo: 'Progress payment — 40%' },
|
||||||
|
{ id: 'rcv_017_3', from: 'Farmers Insurance', method: 'ACH', amount: 5880, date: '2026-04-28', refNumber: 'ACH-2017-03', memo: 'Final payment — 30%' },
|
||||||
|
],
|
||||||
changeOrders: [
|
changeOrders: [
|
||||||
{ id: 'CO-017-01', title: 'Supplemental — Ice & Water Barrier', amount: 1800, status: 'approved', description: 'Insurance adjuster agreed to add ice/water shield on all valleys and eaves.' },
|
{ id: 'CO-017-01', title: 'Supplemental — Ice & Water Barrier', amount: 1800, status: 'approved', description: 'Insurance adjuster agreed to add ice/water shield on all valleys and eaves.' },
|
||||||
],
|
],
|
||||||
@@ -3640,8 +3656,8 @@ const MOCK_PROJECTS = [
|
|||||||
issueLog: [],
|
issueLog: [],
|
||||||
paymentSchedule: [
|
paymentSchedule: [
|
||||||
{ id: 'ps_017_1', milestone: 'Deposit — 30%', amount: 5880, dueDate: '2026-03-28', status: 'paid', paidDate: '2026-03-28' },
|
{ id: 'ps_017_1', milestone: 'Deposit — 30%', amount: 5880, dueDate: '2026-03-28', status: 'paid', paidDate: '2026-03-28' },
|
||||||
{ id: 'ps_017_2', milestone: 'Progress — 40%', amount: 7840, dueDate: '2026-04-25', status: 'pending' },
|
{ id: 'ps_017_2', milestone: 'Progress — 40%', amount: 7840, dueDate: '2026-04-25', status: 'paid', paidDate: '2026-04-25' },
|
||||||
{ id: 'ps_017_3', milestone: 'Final — 30%', amount: 5880, dueDate: '2026-04-28', status: 'pending' },
|
{ id: 'ps_017_3', milestone: 'Final — 30%', amount: 5880, dueDate: '2026-04-28', status: 'paid', paidDate: '2026-04-28' },
|
||||||
],
|
],
|
||||||
invoices: [],
|
invoices: [],
|
||||||
milestones: [
|
milestones: [
|
||||||
|
|||||||
@@ -79,9 +79,6 @@ const DemoCheckout = () => {
|
|||||||
<Row label="CVC" value="123" />
|
<Row label="CVC" value="123" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="flex items-center gap-1.5 text-[11px] text-emerald-600 dark:text-emerald-400 mt-2">
|
|
||||||
<CheckCircle2 size={12} /> Test card pre-filled for the demo — just press Pay.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handlePay}
|
onClick={handlePay}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
* closing the spec's loop (§5). Front-end demo only — no real platform or backend.
|
* closing the spec's loop (§5). Front-end demo only — no real platform or backend.
|
||||||
*/
|
*/
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams, useNavigate, useLocation } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
ShieldCheck, CheckCircle2, ArrowRight, Loader2, Megaphone, Lock, Phone,
|
ShieldCheck, CheckCircle2, ArrowRight, ArrowLeft, Loader2, Megaphone, Lock, Phone,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { BLUEPRINT_BY_ID, BLUEPRINTS } from './data/blueprints.js';
|
import { BLUEPRINT_BY_ID, BLUEPRINTS } from './data/blueprints.js';
|
||||||
@@ -54,6 +54,11 @@ const inputCls =
|
|||||||
|
|
||||||
export default function PublicAdLanding() {
|
export default function PublicAdLanding() {
|
||||||
const [params] = useSearchParams();
|
const [params] = useSearchParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
// Only show the "Back" control when this page was reached via in-app navigation
|
||||||
|
// (i.e. a preview opened from the Ad Engine) — a real ad click lands with no app history.
|
||||||
|
const cameFromApp = location.key !== 'default';
|
||||||
|
|
||||||
const blueprint = BLUEPRINT_BY_ID[params.get('c')] || BLUEPRINTS[0];
|
const blueprint = BLUEPRINT_BY_ID[params.get('c')] || BLUEPRINTS[0];
|
||||||
const platformId = getPlatform(params.get('src')) ? params.get('src') : 'meta';
|
const platformId = getPlatform(params.get('src')) ? params.get('src') : 'meta';
|
||||||
@@ -113,6 +118,14 @@ export default function PublicAdLanding() {
|
|||||||
<p className="text-[11px] text-zinc-400 mt-4 flex items-center justify-center gap-1">
|
<p className="text-[11px] text-zinc-400 mt-4 flex items-center justify-center gap-1">
|
||||||
<ShieldCheck size={12} /> Your information is kept private and used only to contact you about this request.
|
<ShieldCheck size={12} /> Your information is kept private and used only to contact you about this request.
|
||||||
</p>
|
</p>
|
||||||
|
{cameFromApp && (
|
||||||
|
<button
|
||||||
|
onClick={() => navigate(-1)}
|
||||||
|
className="mt-6 inline-flex items-center gap-1.5 text-sm font-semibold text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white transition-colors"
|
||||||
|
>
|
||||||
|
<ArrowLeft size={16} /> Back to Ad Engine
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -120,6 +133,18 @@ export default function PublicAdLanding() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-[100dvh] w-full bg-zinc-50 dark:bg-[#09090b]">
|
<div className="min-h-[100dvh] w-full bg-zinc-50 dark:bg-[#09090b]">
|
||||||
|
{/* Back to Ad Engine — only when opened as a preview from inside the CRM */}
|
||||||
|
{cameFromApp && (
|
||||||
|
<div className="max-w-2xl mx-auto px-4 pt-4">
|
||||||
|
<button
|
||||||
|
onClick={() => navigate(-1)}
|
||||||
|
className="inline-flex items-center gap-1.5 text-sm font-semibold text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white transition-colors"
|
||||||
|
>
|
||||||
|
<ArrowLeft size={16} /> Back to Ad Engine
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Sponsored banner — simulates the ad context */}
|
{/* Sponsored banner — simulates the ad context */}
|
||||||
<div className="w-full bg-zinc-900 text-white/80 text-[11px] py-1.5 px-4 flex items-center justify-center gap-1.5">
|
<div className="w-full bg-zinc-900 text-white/80 text-[11px] py-1.5 px-4 flex items-center justify-center gap-1.5">
|
||||||
<Megaphone size={12} />
|
<Megaphone size={12} />
|
||||||
|
|||||||
Reference in New Issue
Block a user