repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
The Living OS cockpit
stars
latest
clone command
git clone gitlawb://did:key:z6Mku78K...XywC/living-os-cockp...git clone gitlawb://did:key:z6Mku78K.../living-os-cockp...59751530feat: surface worker supervisor health in live work8h ago| #1 | 'use client'; |
| #2 | |
| #3 | import Link from 'next/link'; |
| #4 | import type { CSSProperties } from 'react'; |
| #5 | import { useMemo, useState } from 'react'; |
| #6 | import { Check, Circle, FileText, IdCard, Landmark, Upload } from 'lucide-react'; |
| #7 | |
| #8 | const STEPS = [ |
| #9 | { id: 0, label: 'Identity', short: 'Who You Are' }, |
| #10 | { id: 1, label: 'Trust', short: 'Your Trust' }, |
| #11 | { id: 2, label: 'Branding', short: 'Seal and Colors' }, |
| #12 | { id: 3, label: 'Registration', short: 'Filing Numbers' }, |
| #13 | { id: 4, label: 'Secured Party', short: 'Creditor Status' }, |
| #14 | { id: 5, label: 'Documents', short: 'Document Package' }, |
| #15 | { id: 6, label: 'Activate', short: 'Final Review' }, |
| #16 | ]; |
| #17 | |
| #18 | const PALETTE_PRESETS = [ |
| #19 | { |
| #20 | id: 'eternal', |
| #21 | label: 'Eternal Gold', |
| #22 | primary: '#D4AF37', |
| #23 | secondary: '#050505', |
| #24 | accent: '#3B82F6', |
| #25 | }, |
| #26 | { |
| #27 | id: 'edinburgh', |
| #28 | label: 'Edinburgh Trust', |
| #29 | primary: '#C9A84C', |
| #30 | secondary: '#0A0A0A', |
| #31 | accent: '#7DD3FC', |
| #32 | }, |
| #33 | { |
| #34 | id: 'archive', |
| #35 | label: 'Archive Black', |
| #36 | primary: '#F4D58D', |
| #37 | secondary: '#111111', |
| #38 | accent: '#C9A86A', |
| #39 | }, |
| #40 | { |
| #41 | id: 'living-blue', |
| #42 | label: 'Living Blue', |
| #43 | primary: '#D4AF37', |
| #44 | secondary: '#000000', |
| #45 | accent: '#3B82F6', |
| #46 | }, |
| #47 | ]; |
| #48 | |
| #49 | const DOC_OPTIONS = [ |
| #50 | 'Trust Charter', |
| #51 | 'Affidavit of Identity', |
| #52 | 'Private ID Card', |
| #53 | 'Bond Certificate', |
| #54 | 'Private Money Order', |
| #55 | 'UCC-1 Financing Statement', |
| #56 | ]; |
| #57 | |
| #58 | const UCC_FORMATS: Record<string, RegExp> = { |
| #59 | Texas: /^[0-9]{8,12}[A-Z]?$/i, |
| #60 | Nevada: /^[0-9]{8,14}$/i, |
| #61 | Arizona: /^[0-9A-Z-]{8,18}$/i, |
| #62 | 'New Mexico': /^[0-9A-Z-]{8,18}$/i, |
| #63 | }; |
| #64 | |
| #65 | type SealOption = { |
| #66 | id: string; |
| #67 | label: string; |
| #68 | mark: string; |
| #69 | ring: string; |
| #70 | }; |
| #71 | |
| #72 | type TrustForm = { |
| #73 | fullName: string; |
| #74 | photoLabel: string; |
| #75 | trustNameMode: string; |
| #76 | customTrustName: string; |
| #77 | trustType: string; |
| #78 | primaryColor: string; |
| #79 | secondaryColor: string; |
| #80 | accentColor: string; |
| #81 | uccFiling: string; |
| #82 | uccState: string; |
| #83 | ein: string; |
| #84 | securedParty: boolean; |
| #85 | }; |
| #86 | |
| #87 | function surnameFromName(name: string) { |
| #88 | return name.trim().split(/\s+/).filter(Boolean).slice(-1)[0] || 'Surname'; |
| #89 | } |
| #90 | |
| #91 | function trustInitials(name: string) { |
| #92 | return name |
| #93 | .split(/\s+/) |
| #94 | .filter(part => !['of', 'the', 'private', 'express', 'trust', 'estate', 'family'].includes(part.toLowerCase())) |
| #95 | .slice(0, 3) |
| #96 | .map(part => part[0]?.toUpperCase()) |
| #97 | .join(''); |
| #98 | } |
| #99 | |
| #100 | function formatDate() { |
| #101 | return new Date().toLocaleDateString('en-US', { |
| #102 | month: 'long', |
| #103 | day: '2-digit', |
| #104 | year: 'numeric', |
| #105 | }); |
| #106 | } |
| #107 | |
| #108 | export default function TrustSetupPage() { |
| #109 | const [step, setStep] = useState(0); |
| #110 | const [sealPreview, setSealPreview] = useState<string | null>(null); |
| #111 | const [generatedSeals, setGeneratedSeals] = useState<SealOption[]>([]); |
| #112 | const [selectedSeal, setSelectedSeal] = useState<SealOption | null>(null); |
| #113 | const [sealPrompt, setSealPrompt] = useState('dragon, lawful standing, gold seal, black field'); |
| #114 | const [sealMaterialized, setSealMaterialized] = useState(false); |
| #115 | const [form, setForm] = useState<TrustForm>({ |
| #116 | fullName: 'King Bau', |
| #117 | photoLabel: 'KB', |
| #118 | trustNameMode: 'house', |
| #119 | customTrustName: '', |
| #120 | trustType: 'Private Express Trust', |
| #121 | primaryColor: '#D4AF37', |
| #122 | secondaryColor: '#050505', |
| #123 | accentColor: '#3B82F6', |
| #124 | uccFiling: '20250137020X', |
| #125 | uccState: 'Texas', |
| #126 | ein: '', |
| #127 | securedParty: true, |
| #128 | }); |
| #129 | |
| #130 | const surname = surnameFromName(form.fullName); |
| #131 | const trustSuggestions = useMemo( |
| #132 | () => [ |
| #133 | { id: 'house', label: `House of ${surname} Private Express Trust` }, |
| #134 | { id: 'estate', label: `${surname} Family Estate Trust` }, |
| #135 | { id: 'private', label: `${form.fullName || 'Name'} Private Trust` }, |
| #136 | { id: 'custom', label: 'Custom trust name' }, |
| #137 | ], |
| #138 | [form.fullName, surname] |
| #139 | ); |
| #140 | |
| #141 | const trustName = form.trustNameMode === 'custom' |
| #142 | ? form.customTrustName || 'Custom Private Trust' |
| #143 | : trustSuggestions.find(option => option.id === form.trustNameMode)?.label || trustSuggestions[0].label; |
| #144 | |
| #145 | const uccPattern = UCC_FORMATS[form.uccState] || /^[0-9A-Z-]{6,24}$/i; |
| #146 | const uccLooksValid = !form.uccFiling || uccPattern.test(form.uccFiling.trim()); |
| #147 | const selectedSealMarkup = sealPreview || selectedSeal; |
| #148 | |
| #149 | const update = (key: keyof TrustForm, value: string | boolean) => { |
| #150 | setForm(previous => ({ ...previous, [key]: value })); |
| #151 | }; |
| #152 | |
| #153 | const setPalette = (preset: (typeof PALETTE_PRESETS)[number]) => { |
| #154 | setForm(previous => ({ |
| #155 | ...previous, |
| #156 | primaryColor: preset.primary, |
| #157 | secondaryColor: preset.secondary, |
| #158 | accentColor: preset.accent, |
| #159 | })); |
| #160 | }; |
| #161 | |
| #162 | const onSealFile = (file?: File) => { |
| #163 | if (!file) return; |
| #164 | const reader = new FileReader(); |
| #165 | reader.onload = event => { |
| #166 | setSealPreview(String(event.target?.result || '')); |
| #167 | setSelectedSeal(null); |
| #168 | setSealMaterialized(true); |
| #169 | window.setTimeout(() => setSealMaterialized(false), 1400); |
| #170 | }; |
| #171 | reader.readAsDataURL(file); |
| #172 | }; |
| #173 | |
| #174 | const generateSealStudies = () => { |
| #175 | const terms = sealPrompt.split(/[,\s]+/).filter(Boolean); |
| #176 | const mark = terms.find(term => /^[a-z]/i.test(term))?.slice(0, 2).toUpperCase() || trustInitials(trustName); |
| #177 | const options = [ |
| #178 | { id: 'standard', label: 'Formal round seal', mark, ring: 'single' }, |
| #179 | { id: 'estate', label: 'Estate ring seal', mark: trustInitials(trustName), ring: 'double' }, |
| #180 | { id: 'instrument', label: 'Instrument seal', mark: 'UCC', ring: 'single' }, |
| #181 | { id: 'trustee', label: 'Trustee mark', mark: surname.slice(0, 2).toUpperCase(), ring: 'double' }, |
| #182 | ]; |
| #183 | setGeneratedSeals(options); |
| #184 | setSelectedSeal(options[0]); |
| #185 | setSealPreview(null); |
| #186 | setSealMaterialized(true); |
| #187 | window.setTimeout(() => setSealMaterialized(false), 1400); |
| #188 | }; |
| #189 | |
| #190 | const style = { |
| #191 | '--trust-primary': form.primaryColor, |
| #192 | '--trust-secondary': form.secondaryColor, |
| #193 | '--trust-accent': form.accentColor, |
| #194 | } as CSSProperties; |
| #195 | |
| #196 | return ( |
| #197 | <main className="trust-wizard-page" style={style}> |
| #198 | <div className="trust-wizard-shell"> |
| #199 | <header className="trust-wizard-header"> |
| #200 | <Link href="/" className="trust-back-link">Back to cockpit</Link> |
| #201 | <div> |
| #202 | <p className="trust-eyebrow">Trust Estate Setup</p> |
| #203 | <h1>{trustName}</h1> |
| #204 | <p> |
| #205 | Build the member trust profile used by generated instruments, seals, private IDs, and estate records. |
| #206 | </p> |
| #207 | </div> |
| #208 | </header> |
| #209 | |
| #210 | <Stepper step={step} setStep={setStep} /> |
| #211 | |
| #212 | <div className="trust-wizard-grid"> |
| #213 | <section className="trust-wizard-card"> |
| #214 | <div key={step} className="trust-step-panel"> |
| #215 | <StepContent |
| #216 | step={step} |
| #217 | form={form} |
| #218 | update={update} |
| #219 | trustSuggestions={trustSuggestions} |
| #220 | trustName={trustName} |
| #221 | uccLooksValid={uccLooksValid} |
| #222 | sealPrompt={sealPrompt} |
| #223 | setSealPrompt={setSealPrompt} |
| #224 | sealPreview={sealPreview} |
| #225 | selectedSeal={selectedSeal} |
| #226 | generatedSeals={generatedSeals} |
| #227 | setSelectedSeal={setSelectedSeal} |
| #228 | onSealFile={onSealFile} |
| #229 | generateSealStudies={generateSealStudies} |
| #230 | setPalette={setPalette} |
| #231 | /> |
| #232 | </div> |
| #233 | |
| #234 | <div className="trust-step-actions"> |
| #235 | <button |
| #236 | type="button" |
| #237 | className="btn-ghost rounded px-4 py-2 text-sm" |
| #238 | disabled={step === 0} |
| #239 | onClick={() => setStep(current => Math.max(0, current - 1))} |
| #240 | > |
| #241 | Previous |
| #242 | </button> |
| #243 | <button |
| #244 | type="button" |
| #245 | className="btn-gold rounded px-4 py-2 text-sm" |
| #246 | onClick={() => setStep(current => Math.min(STEPS.length - 1, current + 1))} |
| #247 | > |
| #248 | {step === STEPS.length - 1 ? 'Review Complete' : 'Continue'} |
| #249 | </button> |
| #250 | </div> |
| #251 | </section> |
| #252 | |
| #253 | <aside className="trust-preview-column"> |
| #254 | <LivePreviews |
| #255 | trustName={trustName} |
| #256 | fullName={form.fullName} |
| #257 | photoLabel={form.photoLabel} |
| #258 | uccFiling={form.uccFiling} |
| #259 | uccState={form.uccState} |
| #260 | ein={form.ein} |
| #261 | sealPreview={sealPreview} |
| #262 | selectedSeal={selectedSeal} |
| #263 | sealMaterialized={sealMaterialized} |
| #264 | /> |
| #265 | </aside> |
| #266 | </div> |
| #267 | </div> |
| #268 | </main> |
| #269 | ); |
| #270 | } |
| #271 | |
| #272 | function Stepper({ step, setStep }: { step: number; setStep: (step: number) => void }) { |
| #273 | return ( |
| #274 | <nav className="trust-stepper" aria-label="Trust setup progress"> |
| #275 | {STEPS.map(item => ( |
| #276 | <button |
| #277 | key={item.id} |
| #278 | type="button" |
| #279 | className={`trust-step ${item.id === step ? 'active' : ''} ${item.id < step ? 'complete' : ''}`} |
| #280 | onClick={() => setStep(item.id)} |
| #281 | > |
| #282 | <span>{item.id < step ? <Check size={14} /> : item.id + 1}</span> |
| #283 | <strong>{item.label}</strong> |
| #284 | <small>{item.short}</small> |
| #285 | </button> |
| #286 | ))} |
| #287 | </nav> |
| #288 | ); |
| #289 | } |
| #290 | |
| #291 | function StepContent(props: { |
| #292 | step: number; |
| #293 | form: any; |
| #294 | update: (key: keyof TrustForm, value: string | boolean) => void; |
| #295 | trustSuggestions: { id: string; label: string }[]; |
| #296 | trustName: string; |
| #297 | uccLooksValid: boolean; |
| #298 | sealPrompt: string; |
| #299 | setSealPrompt: (value: string) => void; |
| #300 | sealPreview: string | null; |
| #301 | selectedSeal: SealOption | null; |
| #302 | generatedSeals: SealOption[]; |
| #303 | setSelectedSeal: (seal: SealOption) => void; |
| #304 | onSealFile: (file?: File) => void; |
| #305 | generateSealStudies: () => void; |
| #306 | setPalette: (preset: (typeof PALETTE_PRESETS)[number]) => void; |
| #307 | }) { |
| #308 | const { |
| #309 | step, |
| #310 | form, |
| #311 | update, |
| #312 | trustSuggestions, |
| #313 | trustName, |
| #314 | uccLooksValid, |
| #315 | sealPrompt, |
| #316 | setSealPrompt, |
| #317 | sealPreview, |
| #318 | selectedSeal, |
| #319 | generatedSeals, |
| #320 | setSelectedSeal, |
| #321 | onSealFile, |
| #322 | generateSealStudies, |
| #323 | setPalette, |
| #324 | } = props; |
| #325 | |
| #326 | if (step === 0) { |
| #327 | return ( |
| #328 | <> |
| #329 | <PanelHeader title="Identity" text="The trust record begins with the living man or woman establishing the estate." /> |
| #330 | <div className="field-grid"> |
| #331 | <Field label="Full name" value={form.fullName} onChange={value => update('fullName', value)} /> |
| #332 | <Field label="Photo initials" value={form.photoLabel} onChange={value => update('photoLabel', value.slice(0, 3).toUpperCase())} /> |
| #333 | </div> |
| #334 | </> |
| #335 | ); |
| #336 | } |
| #337 | |
| #338 | if (step === 1) { |
| #339 | return ( |
| #340 | <> |
| #341 | <PanelHeader |
| #342 | title="Trust Naming" |
| #343 | text="The House naming convention gives the estate a clear private capacity. Members may keep the suggested House name or choose their own trust name." |
| #344 | /> |
| #345 | <div className="trust-name-options"> |
| #346 | {trustSuggestions.map(option => ( |
| #347 | <button |
| #348 | type="button" |
| #349 | key={option.id} |
| #350 | className={`trust-name-option ${form.trustNameMode === option.id ? 'selected' : ''}`} |
| #351 | onClick={() => update('trustNameMode', option.id)} |
| #352 | > |
| #353 | <span>{option.label}</span> |
| #354 | {option.id === 'house' && <small>Recommended House structure</small>} |
| #355 | </button> |
| #356 | ))} |
| #357 | </div> |
| #358 | {form.trustNameMode === 'custom' && ( |
| #359 | <Field label="Custom trust name" value={form.customTrustName} onChange={value => update('customTrustName', value)} /> |
| #360 | )} |
| #361 | <div className="tradition-note"> |
| #362 | <Landmark size={17} /> |
| #363 | <p> |
| #364 | House names carry historic continuity and make the trustee capacity visible on every instrument. |
| #365 | </p> |
| #366 | </div> |
| #367 | <Field label="Trust type" value={form.trustType} onChange={value => update('trustType', value)} /> |
| #368 | </> |
| #369 | ); |
| #370 | } |
| #371 | |
| #372 | if (step === 2) { |
| #373 | return ( |
| #374 | <> |
| #375 | <PanelHeader |
| #376 | title="Seal and Branding" |
| #377 | text="The seal verifies the member's trust standing on generated instruments. Upload an existing seal or generate studies with Aethon." |
| #378 | /> |
| #379 | <div className="seal-workbench"> |
| #380 | <label className="seal-dropzone"> |
| #381 | <Upload size={20} /> |
| #382 | <span>Upload your seal</span> |
| #383 | <small>PNG, JPG, or WebP</small> |
| #384 | <input type="file" accept="image/*" onChange={event => onSealFile(event.target.files?.[0])} /> |
| #385 | </label> |
| #386 | <div className="seal-generate-box"> |
| #387 | <label>Generate with Aethon</label> |
| #388 | <textarea value={sealPrompt} onChange={event => setSealPrompt(event.target.value)} /> |
| #389 | <button type="button" className="btn-gold rounded px-3 py-2 text-xs" onClick={generateSealStudies}> |
| #390 | Generate Seal Studies |
| #391 | </button> |
| #392 | </div> |
| #393 | </div> |
| #394 | |
| #395 | {(sealPreview || generatedSeals.length > 0) && ( |
| #396 | <div className="seal-study-grid"> |
| #397 | {sealPreview && ( |
| #398 | <button type="button" className="seal-study selected"> |
| #399 | <img src={sealPreview} alt="Uploaded seal preview" /> |
| #400 | <span>Uploaded seal</span> |
| #401 | </button> |
| #402 | )} |
| #403 | {generatedSeals.map(option => ( |
| #404 | <button |
| #405 | type="button" |
| #406 | key={option.id} |
| #407 | className={`seal-study ${selectedSeal?.id === option.id ? 'selected' : ''}`} |
| #408 | onClick={() => setSelectedSeal(option)} |
| #409 | > |
| #410 | <GeneratedSeal option={option} compact /> |
| #411 | <span>{option.label}</span> |
| #412 | </button> |
| #413 | ))} |
| #414 | </div> |
| #415 | )} |
| #416 | |
| #417 | <div className="palette-grid"> |
| #418 | {PALETTE_PRESETS.map(preset => ( |
| #419 | <button type="button" className="palette-preset" key={preset.id} onClick={() => setPalette(preset)}> |
| #420 | <span className="palette-swatches"> |
| #421 | <i style={{ background: preset.primary }} /> |
| #422 | <i style={{ background: preset.secondary }} /> |
| #423 | <i style={{ background: preset.accent }} /> |
| #424 | </span> |
| #425 | <strong>{preset.label}</strong> |
| #426 | </button> |
| #427 | ))} |
| #428 | </div> |
| #429 | <div className="field-grid three"> |
| #430 | <Field label="Primary color" value={form.primaryColor} onChange={value => update('primaryColor', value)} type="color" /> |
| #431 | <Field label="Field color" value={form.secondaryColor} onChange={value => update('secondaryColor', value)} type="color" /> |
| #432 | <Field label="Accent color" value={form.accentColor} onChange={value => update('accentColor', value)} type="color" /> |
| #433 | </div> |
| #434 | </> |
| #435 | ); |
| #436 | } |
| #437 | |
| #438 | if (step === 3) { |
| #439 | return ( |
| #440 | <> |
| #441 | <PanelHeader |
| #442 | title="Registration" |
| #443 | text="A UCC-1 filing gives public notice of the secured party interest. Enter the filing number if perfection has already been completed." |
| #444 | /> |
| #445 | <div className="field-grid"> |
| #446 | <Field label="UCC-1 filing number" value={form.uccFiling} onChange={value => update('uccFiling', value)} /> |
| #447 | <Field label="Filing state" value={form.uccState} onChange={value => update('uccState', value)} /> |
| #448 | <Field label="EIN" value={form.ein} onChange={value => update('ein', value)} /> |
| #449 | </div> |
| #450 | <div className={`ucc-validation ${uccLooksValid ? 'valid' : 'invalid'}`}> |
| #451 | <Circle size={12} /> |
| #452 | <span>{uccLooksValid ? 'Filing format looks usable for this state.' : 'Check this filing number format before generating final instruments.'}</span> |
| #453 | </div> |
| #454 | <a className="filing-link" href="/trust/learn">View filing instructions</a> |
| #455 | </> |
| #456 | ); |
| #457 | } |
| #458 | |
| #459 | if (step === 4) { |
| #460 | return ( |
| #461 | <> |
| #462 | <PanelHeader title="Secured Party" text="Mark whether the estate is being configured for secured party creditor standing." /> |
| #463 | <button |
| #464 | type="button" |
| #465 | className={`secured-toggle ${form.securedParty ? 'selected' : ''}`} |
| #466 | onClick={() => update('securedParty', !form.securedParty)} |
| #467 | > |
| #468 | <span>{form.securedParty ? 'Secured Party Creditor path enabled' : 'Enable Secured Party Creditor path'}</span> |
| #469 | <small>Used to prepare UCC-1 and bond-related documents.</small> |
| #470 | </button> |
| #471 | </> |
| #472 | ); |
| #473 | } |
| #474 | |
| #475 | if (step === 5) { |
| #476 | return ( |
| #477 | <> |
| #478 | <PanelHeader title="Document Package" text="Select the instruments Aethon should prepare with the trust branding applied." /> |
| #479 | <div className="doc-check-grid"> |
| #480 | {DOC_OPTIONS.map(option => ( |
| #481 | <label key={option}> |
| #482 | <input type="checkbox" defaultChecked /> |
| #483 | <span>{option}</span> |
| #484 | </label> |
| #485 | ))} |
| #486 | </div> |
| #487 | </> |
| #488 | ); |
| #489 | } |
| #490 | |
| #491 | return ( |
| #492 | <> |
| #493 | <PanelHeader title="Activate" text="Review the trust identity before final generation. The live previews show the member-facing document treatment." /> |
| #494 | <div className="activate-summary"> |
| #495 | <div><span>Trust</span><strong>{trustName}</strong></div> |
| #496 | <div><span>Trustee</span><strong>{form.fullName}, Trustee</strong></div> |
| #497 | <div><span>UCC filing</span><strong>{form.uccFiling || 'Pending'}</strong></div> |
| #498 | <div><span>Seal</span><strong>{sealPreview || selectedSeal ? 'Ready' : 'Pending'}</strong></div> |
| #499 | </div> |
| #500 | </> |
| #501 | ); |
| #502 | } |
| #503 | |
| #504 | function PanelHeader({ title, text }: { title: string; text: string }) { |
| #505 | return ( |
| #506 | <div className="trust-panel-header"> |
| #507 | <p>Step</p> |
| #508 | <h2>{title}</h2> |
| #509 | <span>{text}</span> |
| #510 | </div> |
| #511 | ); |
| #512 | } |
| #513 | |
| #514 | function Field({ label, value, onChange, type = 'text' }: { label: string; value: string; onChange: (value: string) => void; type?: string }) { |
| #515 | return ( |
| #516 | <label className="trust-field"> |
| #517 | <span>{label}</span> |
| #518 | <input type={type} value={value} onChange={event => onChange(event.target.value)} /> |
| #519 | </label> |
| #520 | ); |
| #521 | } |
| #522 | |
| #523 | function GeneratedSeal({ option, compact = false }: { option: SealOption; compact?: boolean }) { |
| #524 | return ( |
| #525 | <div className={`generated-seal ${option.ring === 'double' ? 'double' : ''} ${compact ? 'compact' : ''}`}> |
| #526 | <span>{option.mark}</span> |
| #527 | </div> |
| #528 | ); |
| #529 | } |
| #530 | |
| #531 | function SealMark({ sealPreview, selectedSeal, materialized }: { sealPreview: string | null; selectedSeal: SealOption | null; materialized: boolean }) { |
| #532 | return ( |
| #533 | <div className={`preview-seal ${materialized ? 'materialize' : ''}`}> |
| #534 | {sealPreview ? <img src={sealPreview} alt="Trust seal" /> : <GeneratedSeal option={selectedSeal || { id: 'default', label: 'Trust seal', mark: 'SEAL', ring: 'double' }} />} |
| #535 | </div> |
| #536 | ); |
| #537 | } |
| #538 | |
| #539 | function LivePreviews(props: { |
| #540 | trustName: string; |
| #541 | fullName: string; |
| #542 | photoLabel: string; |
| #543 | uccFiling: string; |
| #544 | uccState: string; |
| #545 | ein: string; |
| #546 | sealPreview: string | null; |
| #547 | selectedSeal: SealOption | null; |
| #548 | sealMaterialized: boolean; |
| #549 | }) { |
| #550 | const { trustName, fullName, photoLabel, uccFiling, uccState, ein, sealPreview, selectedSeal, sealMaterialized } = props; |
| #551 | return ( |
| #552 | <div className="trust-preview-stack"> |
| #553 | <div className="preview-header"> |
| #554 | <span>Live instrument preview</span> |
| #555 | <strong>Updates with trust branding</strong> |
| #556 | </div> |
| #557 | |
| #558 | <article className="pmo-preview"> |
| #559 | <SealMark sealPreview={sealPreview} selectedSeal={selectedSeal} materialized={sealMaterialized} /> |
| #560 | <p className="instrument-label">Private Money Order</p> |
| #561 | <h3>{trustName}</h3> |
| #562 | <div className="pmo-line"><span>Obligor</span><strong>Tesla Inc.</strong></div> |
| #563 | <div className="pmo-line"><span>Amount</span><strong>$50,000.00</strong></div> |
| #564 | <div className="pmo-line"><span>UCC Reference</span><strong>{uccFiling || 'Pending'}</strong></div> |
| #565 | <footer>Issued {formatDate()}</footer> |
| #566 | </article> |
| #567 | |
| #568 | <article className="id-preview"> |
| #569 | <div className="id-front"> |
| #570 | <div className="id-photo">{photoLabel || trustInitials(fullName)}</div> |
| #571 | <div> |
| #572 | <p>Private ID Card</p> |
| #573 | <h3>{fullName || 'Member Name'}</h3> |
| #574 | <span>{trustName}</span> |
| #575 | </div> |
| #576 | <SealMark sealPreview={sealPreview} selectedSeal={selectedSeal} materialized={false} /> |
| #577 | </div> |
| #578 | <div className="id-back"> |
| #579 | <div className="id-watermark">{trustInitials(trustName)}</div> |
| #580 | <span>Trust ID</span> |
| #581 | <strong>{trustInitials(trustName)}-TRUST-{new Date().getFullYear()}-001</strong> |
| #582 | <span>Filing</span> |
| #583 | <strong>{uccFiling || 'Pending'} {uccState ? `- ${uccState}` : ''}</strong> |
| #584 | <span>EIN</span> |
| #585 | <strong>{ein || 'Pending'}</strong> |
| #586 | </div> |
| #587 | </article> |
| #588 | |
| #589 | <article className="affidavit-preview"> |
| #590 | <div> |
| #591 | <p>Affidavit of Identity</p> |
| #592 | <h3>{trustName}</h3> |
| #593 | <span>{fullName || 'Member Name'}, Trustee</span> |
| #594 | </div> |
| #595 | <SealMark sealPreview={sealPreview} selectedSeal={selectedSeal} materialized={false} /> |
| #596 | </article> |
| #597 | </div> |
| #598 | ); |
| #599 | } |
| #600 |