forked from Goutam/lynkeduppro-crm
Sidebar light-theme fix; remove Property step from registration
- dashboard sidebar now uses the --sidebar token so it turns white in light mode instead of staying black; active nav item stays readable - registration: drop the Property / Job ID step (job ID + find-by-address), flow is now Account -> Verify -> Address with steps renumbered Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -239,7 +239,7 @@
|
|||||||
.dash-root .view { position: relative; z-index: 1; }
|
.dash-root .view { position: relative; z-index: 1; }
|
||||||
|
|
||||||
/* ---- sidebar (premium nav) ---- */
|
/* ---- sidebar (premium nav) ---- */
|
||||||
.dash-root .dash-sidebar { width: 236px; flex: 0 0 236px; background: #040404 }
|
.dash-root .dash-sidebar { width: 236px; flex: 0 0 236px; background: var(--sidebar); }
|
||||||
.dash-root .dash-brand { padding: 20px 18px 16px; }
|
.dash-root .dash-brand { padding: 20px 18px 16px; }
|
||||||
.dash-root .dash-brand .bk { font-size: 15.5px; font-weight: 800; letter-spacing: -0.01em; }
|
.dash-root .dash-brand .bk { font-size: 15.5px; font-weight: 800; letter-spacing: -0.01em; }
|
||||||
.dash-root .dash-nav { padding: 4px 12px 14px; }
|
.dash-root .dash-nav { padding: 4px 12px 14px; }
|
||||||
@@ -280,6 +280,14 @@
|
|||||||
}
|
}
|
||||||
.dash-root .nav-item.active svg { color: #fff; }
|
.dash-root .nav-item.active svg { color: #fff; }
|
||||||
|
|
||||||
|
/* Light theme: the faint orange gradient + white text is invisible on a
|
||||||
|
white sidebar, so use readable orange text/icon instead. */
|
||||||
|
.dash-root[data-theme="light"] .nav-item.active {
|
||||||
|
background: linear-gradient(90deg, rgba(253, 169, 19, 0) 0%, rgba(253, 169, 19, 0.16) 100%);
|
||||||
|
color: var(--orange);
|
||||||
|
}
|
||||||
|
.dash-root[data-theme="light"] .nav-item.active svg { color: var(--orange); }
|
||||||
|
|
||||||
/* ---- coming-soon placeholder ---- */
|
/* ---- coming-soon placeholder ---- */
|
||||||
.dash-root .coming-soon { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 56px 24px; gap: 8px; }
|
.dash-root .coming-soon { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 56px 24px; gap: 8px; }
|
||||||
.dash-root .coming-soon-ic { width: 76px; height: 76px; border-radius: 22px; display: grid; place-items: center; color: var(--orange); background: color-mix(in srgb, var(--orange) 12%, transparent); margin-bottom: 8px; }
|
.dash-root .coming-soon-ic { width: 76px; height: 76px; border-radius: 22px; display: grid; place-items: center; color: var(--orange); background: color-mix(in srgb, var(--orange) 12%, transparent); margin-bottom: 8px; }
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
TERMS, PRIVACY, passwordStrength, type AddrCountry,
|
TERMS, PRIVACY, passwordStrength, type AddrCountry,
|
||||||
} from "./data";
|
} from "./data";
|
||||||
|
|
||||||
const STEPS = ["Account", "Property", "Verify", "Address"];
|
const STEPS = ["Account", "Verify", "Address"];
|
||||||
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
|
||||||
export function RegisterFlow() {
|
export function RegisterFlow() {
|
||||||
@@ -34,11 +34,7 @@ export function RegisterFlow() {
|
|||||||
const [termsOk, setTermsOk] = useState(false);
|
const [termsOk, setTermsOk] = useState(false);
|
||||||
const [privacyOk, setPrivacyOk] = useState(false);
|
const [privacyOk, setPrivacyOk] = useState(false);
|
||||||
|
|
||||||
// step 1
|
// verify step
|
||||||
const [allotment, setAllotment] = useState("");
|
|
||||||
const [plotVerified, setPlotVerified] = useState(false);
|
|
||||||
|
|
||||||
// step 2
|
|
||||||
const [emailVerified, setEmailVerified] = useState(false);
|
const [emailVerified, setEmailVerified] = useState(false);
|
||||||
const [phoneVerified, setPhoneVerified] = useState(false);
|
const [phoneVerified, setPhoneVerified] = useState(false);
|
||||||
|
|
||||||
@@ -53,7 +49,6 @@ export function RegisterFlow() {
|
|||||||
first.trim() && last.trim() && EMAIL_RE.test(sso?.email || email) && phoneOk && pwOk &&
|
first.trim() && last.trim() && EMAIL_RE.test(sso?.email || email) && phoneOk && pwOk &&
|
||||||
termsOk && privacyOk && (isSelf || (alloeIdOk && (isEmployee || (alloeFirst.trim() && alloeLast.trim()))));
|
termsOk && privacyOk && (isSelf || (alloeIdOk && (isEmployee || (alloeFirst.trim() && alloeLast.trim()))));
|
||||||
|
|
||||||
const step1Valid = /^LUP-\d{6}$/.test(allotment) || plotVerified;
|
|
||||||
const step2Valid = emailVerified && phoneVerified;
|
const step2Valid = emailVerified && phoneVerified;
|
||||||
|
|
||||||
function finish() {
|
function finish() {
|
||||||
@@ -88,24 +83,16 @@ export function RegisterFlow() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{step === 1 && (
|
{step === 1 && (
|
||||||
<StepAllotment
|
|
||||||
allotment={allotment} setAllotment={setAllotment}
|
|
||||||
plotVerified={plotVerified} setPlotVerified={setPlotVerified}
|
|
||||||
valid={step1Valid} onBack={() => setStep(0)} onContinue={() => setStep(2)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 2 && (
|
|
||||||
<StepVerify
|
<StepVerify
|
||||||
emailValue={sso?.email || email} cc={cc} phone={phone} country={country}
|
emailValue={sso?.email || email} cc={cc} phone={phone} country={country}
|
||||||
emailVerified={emailVerified} setEmailVerified={setEmailVerified}
|
emailVerified={emailVerified} setEmailVerified={setEmailVerified}
|
||||||
phoneVerified={phoneVerified} setPhoneVerified={setPhoneVerified}
|
phoneVerified={phoneVerified} setPhoneVerified={setPhoneVerified}
|
||||||
valid={step2Valid} onBack={() => setStep(1)} onContinue={() => setStep(3)}
|
valid={step2Valid} onBack={() => setStep(0)} onContinue={() => setStep(2)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{step === 3 && (
|
{step === 2 && (
|
||||||
<StepAddress onBack={() => setStep(2)} onFinish={finish} />
|
<StepAddress onBack={() => setStep(1)} onFinish={finish} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -278,71 +265,7 @@ function StepAccount(p: {
|
|||||||
// module-level reviewed flags (per mount lifetime) — enables the checkboxes after a doc is read
|
// module-level reviewed flags (per mount lifetime) — enables the checkboxes after a doc is read
|
||||||
const reviewed = { terms: false, privacy: false };
|
const reviewed = { terms: false, privacy: false };
|
||||||
|
|
||||||
/* ====================== STEP 1 — ALLOTMENT ====================== */
|
/* ====================== STEP 1 — VERIFY ====================== */
|
||||||
function StepAllotment(p: {
|
|
||||||
allotment: string; setAllotment: (v: string) => void;
|
|
||||||
plotVerified: boolean; setPlotVerified: (v: boolean) => void;
|
|
||||||
valid: boolean; onBack: () => void; onContinue: () => void;
|
|
||||||
}) {
|
|
||||||
const [mode, setMode] = useState<"have" | "forgot">("have");
|
|
||||||
const [houseNo, setHouseNo] = useState("");
|
|
||||||
const [street, setStreet] = useState("");
|
|
||||||
const [city, setCity] = useState("");
|
|
||||||
const [busy, setBusy] = useState(false);
|
|
||||||
const fmtOk = /^LUP-\d{6}$/.test(p.allotment);
|
|
||||||
|
|
||||||
function findPlot() {
|
|
||||||
if (!houseNo || !street || !city) return;
|
|
||||||
setBusy(true);
|
|
||||||
setTimeout(() => { setBusy(false); p.setPlotVerified(true); }, 800);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<StepBack onClick={p.onBack} />
|
|
||||||
<h1>Identify the property</h1>
|
|
||||||
<p className="sub">Find the property by its job ID, or look it up by address.</p>
|
|
||||||
|
|
||||||
<div className="seg" style={{ margin: "16px 0" }}>
|
|
||||||
<button className={mode === "have" ? "on" : ""} onClick={() => setMode("have")}>I have a job ID</button>
|
|
||||||
<button className={mode === "forgot" ? "on" : ""} onClick={() => setMode("forgot")}>Find by address</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{mode === "have" ? (
|
|
||||||
<div className="field">
|
|
||||||
<label className="label">Property / Job ID</label>
|
|
||||||
<input className="input" value={p.allotment} onChange={(e) => p.setAllotment(e.target.value.toUpperCase())} placeholder="LUP-123456" />
|
|
||||||
<span className="faint" style={{ fontSize: 12 }}>Format: LUP- followed by 6 digits.</span>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div>
|
|
||||||
<div className="row gap-3">
|
|
||||||
<div className="field" style={{ width: 120 }}><label className="label">House no.</label><input className="input" value={houseNo} onChange={(e) => setHouseNo(e.target.value)} placeholder="123" /></div>
|
|
||||||
<div className="field grow"><label className="label">Street</label><input className="input" value={street} onChange={(e) => setStreet(e.target.value)} placeholder="Street name" /></div>
|
|
||||||
</div>
|
|
||||||
<div className="field" style={{ marginTop: 12 }}><label className="label">City / ZIP</label><input className="input" value={city} onChange={(e) => setCity(e.target.value)} placeholder="City or ZIP code" /></div>
|
|
||||||
{!p.plotVerified ? (
|
|
||||||
<button className="btn" style={{ marginTop: 12 }} disabled={busy || !(houseNo && street && city)} onClick={findPlot}>
|
|
||||||
{busy ? "Searching…" : "Find my property"}
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<div className="conn-banner conn-green" style={{ marginTop: 12 }}>
|
|
||||||
<Icon name="check" size={16} />
|
|
||||||
<span style={{ letterSpacing: 1 }}>LUP-****** · Verified · {houseNo} {street}, {city}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<p className="demo-hint">Sensitive details stay masked until verified (verify-to-reveal).</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{mode === "have" && p.allotment && !fmtOk && <p className="hint-line">Enter a valid ID like LUP-123456.</p>}
|
|
||||||
|
|
||||||
<button className="btn btn-primary" style={{ marginTop: 16 }} disabled={!p.valid} onClick={p.onContinue}>Continue <Icon name="arrowR" size={16} /></button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ====================== STEP 2 — VERIFY ====================== */
|
|
||||||
function StepVerify(p: {
|
function StepVerify(p: {
|
||||||
emailValue: string; cc: string; phone: string; country: typeof countryCodes[number];
|
emailValue: string; cc: string; phone: string; country: typeof countryCodes[number];
|
||||||
emailVerified: boolean; setEmailVerified: (v: boolean) => void;
|
emailVerified: boolean; setEmailVerified: (v: boolean) => void;
|
||||||
|
|||||||
Reference in New Issue
Block a user