Refine coaching UI and add audio recording

This commit is contained in:
Flatlogic Bot 2026-06-09 17:13:18 +00:00
parent 058b824a5c
commit be3bbea7aa
13 changed files with 481 additions and 332 deletions

View File

@ -170,11 +170,11 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
> >
<div className='flex items-center justify-between'> <div className='flex items-center justify-between'>
<Link href='/dashboard' className='flex items-center gap-3'> <Link href='/dashboard' className='flex items-center gap-3'>
<span className='grid h-8 w-8 place-items-center rounded-full border border-[#b17a1e]/50 bg-[#35b7a5] text-sm font-black text-white'> <span className='grid h-8 w-8 place-items-center rounded-none border border-[#35b7a5]/50 bg-[#35b7a5] text-sm font-black text-white'>
CW CW
</span> </span>
<span> <span>
<span className='block text-sm font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <span className='block text-sm font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
AppWizzy AppWizzy
</span> </span>
<span className='block text-lg font-semibold'> <span className='block text-lg font-semibold'>
@ -184,15 +184,15 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
</Link> </Link>
<button <button
type='button' type='button'
className='grid h-8 w-8 place-items-center rounded-full border border-[#19192d]/10 text-[#72798a] lg:hidden' className='grid h-8 w-8 place-items-center rounded-none border border-[#19192d]/10 text-[#72798a] lg:hidden'
onClick={() => setIsAsideOpen(false)} onClick={() => setIsAsideOpen(false)}
> >
<BaseIcon path={mdiClose} size={18} /> <BaseIcon path={mdiClose} size={18} />
</button> </button>
</div> </div>
<div className='mt-5 rounded-lg border border-[#19192d]/10 bg-white p-4'> <div className='mt-5 rounded-none border border-[#19192d]/10 bg-white p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.2em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.2em] text-[#35b7a5]'>
Today Today
</p> </p>
<p className='mt-2 text-sm leading-6 text-[#72798a]'> <p className='mt-2 text-sm leading-6 text-[#72798a]'>
@ -211,10 +211,10 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
<Link <Link
key={item.href} key={item.href}
href={item.href} href={item.href}
className={`flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-semibold transition ${ className={`flex items-center gap-3 rounded-none px-4 py-3 text-sm font-semibold transition ${
isActive isActive
? 'bg-[#35b7a5] text-white' ? 'bg-[#35b7a5] text-white'
: 'text-[#72798a] hover:bg-[#fbf8f1] hover:text-[#19192d]' : 'text-[#72798a] hover:bg-[#fffdf9] hover:text-[#19192d]'
}`} }`}
> >
<BaseIcon path={item.icon} size={18} /> <BaseIcon path={item.icon} size={18} />
@ -224,8 +224,8 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
})} })}
</nav> </nav>
<div className='absolute inset-x-4 bottom-5 rounded-lg border border-[#19192d]/10 bg-[#fbf8f1] p-4'> <div className='absolute inset-x-4 bottom-5 rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Signed in Signed in
</p> </p>
<p className='mt-2 truncate text-sm font-semibold'> <p className='mt-2 truncate text-sm font-semibold'>
@ -233,7 +233,7 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
</p> </p>
<button <button
type='button' type='button'
className='mt-4 flex w-full items-center justify-center gap-2 rounded-full bg-[#19192d] px-3 py-1.5 text-sm font-semibold text-white' className='mt-4 flex w-full items-center justify-center gap-2 rounded-none bg-[#19192d] px-4 py-2 text-sm font-semibold text-white'
onClick={() => { onClick={() => {
dispatch(logoutUser()); dispatch(logoutUser());
router.push('/login'); router.push('/login');
@ -255,17 +255,17 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
)} )}
<div className='lg:pl-64'> <div className='lg:pl-64'>
<header className='sticky top-0 z-20 border-b border-[#19192d]/10/80 bg-[#fffdf9]/92 px-3 py-2 backdrop-blur lg:px-8'> <header className='sticky top-0 z-20 border-b border-[#19192d]/10/80 bg-[#fffdf9]/92 px-4 py-3 backdrop-blur lg:px-8'>
<div className='flex items-center justify-between'> <div className='flex items-center justify-between'>
<button <button
type='button' type='button'
className='grid h-8 w-8 place-items-center rounded-full border border-[#19192d]/10 bg-white text-[#72798a] lg:hidden' className='grid h-8 w-8 place-items-center rounded-none border border-[#19192d]/10 bg-white text-[#72798a] lg:hidden'
onClick={() => setIsAsideOpen(true)} onClick={() => setIsAsideOpen(true)}
> >
<BaseIcon path={mdiMenu} size={18} /> <BaseIcon path={mdiMenu} size={18} />
</button> </button>
<div className='hidden lg:block'> <div className='hidden lg:block'>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Workspace status Workspace status
</p> </p>
<p className='mt-1 text-sm text-[#72798a]'> <p className='mt-1 text-sm text-[#72798a]'>
@ -276,7 +276,7 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
</div> </div>
<Link <Link
href='/' href='/'
className='rounded-full border border-[#19192d]/10 bg-white px-3 py-1.5 text-sm font-semibold text-[#19192d]' className='rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]'
> >
Public site Public site
</Link> </Link>

View File

@ -48,7 +48,7 @@ function Panel({
}) { }) {
return ( return (
<section <section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`} className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
> >
{children} {children}
</section> </section>
@ -180,9 +180,9 @@ const ClientPortal = () => {
const openItems = (portalClient?.action_items || []).filter((item) => { const openItems = (portalClient?.action_items || []).filter((item) => {
return item.status !== 'done'; return item.status !== 'done';
}); });
const finishedCount = const finishedCount = (portalClient?.action_items || []).filter(
(portalClient?.action_items || []).filter((item) => item.status === 'done') (item) => item.status === 'done',
.length; ).length;
const latestSession = portalClient?.sessions?.[0]; const latestSession = portalClient?.sessions?.[0];
return ( return (
@ -193,14 +193,14 @@ const ClientPortal = () => {
<SectionMain> <SectionMain>
<div className='mx-auto max-w-7xl'> <div className='mx-auto max-w-7xl'>
{!isClientUser && ( {!isClientUser && (
<Panel className='mb-4 p-4'> <Panel className='mb-4 p-6'>
<label className='block text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <label className='block text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Preview as client Preview as client
</label> </label>
<select <select
value={clientId} value={clientId}
onChange={(event) => setClientId(event.target.value)} onChange={(event) => setClientId(event.target.value)}
className='mt-3 w-full rounded-lg border border-[#19192d]/10 bg-white px-3 py-2 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15 md:w-96' className='mt-3 w-full rounded-none border border-[#19192d]/10 bg-white px-4 py-3 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15 md:w-96'
> >
{clients.map((client) => ( {clients.map((client) => (
<option key={client.id} value={client.id}> <option key={client.id} value={client.id}>
@ -212,11 +212,11 @@ const ClientPortal = () => {
)} )}
{portalClient && ( {portalClient && (
<div className='grid gap-4'> <div className='grid gap-6'>
<div className='rounded-lg border border-[#19192d]/10 bg-[#fffdf9] p-5'> <div className='rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-7'>
<div className='grid gap-4 lg:grid-cols-[1fr_280px]'> <div className='grid gap-6 lg:grid-cols-[1fr_280px]'>
<div> <div>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Client workspace Client workspace
</p> </p>
<h1 className='mt-2 text-2xl font-semibold text-[#19192d]'> <h1 className='mt-2 text-2xl font-semibold text-[#19192d]'>
@ -229,7 +229,7 @@ const ClientPortal = () => {
</p> </p>
</div> </div>
<div className='rounded-lg border border-[#19192d]/10 bg-white p-4'> <div className='rounded-none border border-[#19192d]/10 bg-white p-6'>
<div className='flex items-center gap-2 text-sm font-semibold text-[#35b7a5]'> <div className='flex items-center gap-2 text-sm font-semibold text-[#35b7a5]'>
<BaseIcon path={mdiCalendarClock} size={18} /> <BaseIcon path={mdiCalendarClock} size={18} />
Next session Next session
@ -244,7 +244,7 @@ const ClientPortal = () => {
</div> </div>
</div> </div>
<div className='grid gap-4 md:grid-cols-3'> <div className='grid gap-6 md:grid-cols-3'>
<Panel className='p-4'> <Panel className='p-4'>
<p className='text-sm font-semibold text-[#72798a]'> <p className='text-sm font-semibold text-[#72798a]'>
Open commitments Open commitments
@ -271,12 +271,12 @@ const ClientPortal = () => {
</Panel> </Panel>
</div> </div>
<div className='grid gap-4 xl:grid-cols-[0.95fr_1.05fr]'> <div className='grid gap-6 xl:grid-cols-[0.95fr_1.05fr]'>
<div className='space-y-4'> <div className='space-y-4'>
<Panel> <Panel>
<div className='border-b border-[#19192d]/10 p-4'> <div className='border-b border-[#19192d]/10 p-6'>
<div className='flex items-center gap-3'> <div className='flex items-center gap-3'>
<span className='grid h-8 w-8 place-items-center rounded-full bg-[#f3fbf8] text-[#35b7a5]'> <span className='grid h-8 w-8 place-items-center rounded-none bg-[#fffdf9] text-[#35b7a5]'>
<BaseIcon path={mdiCheckCircleOutline} size={18} /> <BaseIcon path={mdiCheckCircleOutline} size={18} />
</span> </span>
<div> <div>
@ -289,25 +289,24 @@ const ClientPortal = () => {
</div> </div>
</div> </div>
</div> </div>
<div className='space-y-3 p-4'> <div className='space-y-3 p-6'>
{(portalClient.action_items || []).map((item) => { {(portalClient.action_items || []).map((item) => {
const isDone = const isDone = item.status === 'done';
item.status === 'done';
return ( return (
<button <button
key={item.id} key={item.id}
type='button' type='button'
className={`flex w-full gap-3 rounded-lg border p-4 text-left transition ${ className={`flex w-full gap-3 rounded-none border p-6 text-left transition ${
isDone isDone
? 'border-[#35b7a5]/30 bg-[#f3fbf8]' ? 'border-[#35b7a5]/30 bg-[#fffdf9]'
: 'border-[#19192d]/10 bg-white hover:bg-[#fffdf9]' : 'border-[#19192d]/10 bg-white hover:bg-[#fffdf9]'
}`} }`}
disabled={updatingItemId === item.id} disabled={updatingItemId === item.id}
onClick={() => toggleItem(item)} onClick={() => toggleItem(item)}
> >
<span <span
className={`mt-0.5 grid h-8 w-8 flex-none place-items-center rounded-full border ${ className={`mt-0.5 grid h-8 w-8 flex-none place-items-center rounded-none border ${
isDone isDone
? 'border-[#35b7a5] bg-[#35b7a5] text-white' ? 'border-[#35b7a5] bg-[#35b7a5] text-white'
: 'border-[#19192d]/10 bg-white text-[#72798a]' : 'border-[#19192d]/10 bg-white text-[#72798a]'
@ -336,7 +335,7 @@ const ClientPortal = () => {
<Panel className='p-4'> <Panel className='p-4'>
<div className='flex items-center gap-3'> <div className='flex items-center gap-3'>
<span className='grid h-8 w-8 place-items-center rounded-full bg-[#fbf8f1] text-[#b17a1e]'> <span className='grid h-8 w-8 place-items-center rounded-none bg-[#fffdf9] text-[#35b7a5]'>
<BaseIcon path={mdiPencilOutline} size={18} /> <BaseIcon path={mdiPencilOutline} size={18} />
</span> </span>
<div> <div>
@ -354,7 +353,7 @@ const ClientPortal = () => {
setReflection(event.target.value); setReflection(event.target.value);
setReflectionSaved(false); setReflectionSaved(false);
}} }}
className='mt-4 min-h-[140px] w-full rounded-lg border border-[#19192d]/10 bg-[#fffdf9] px-3 py-2 text-sm leading-6 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15' className='mt-4 min-h-[140px] w-full rounded-none border border-[#19192d]/10 bg-[#fffdf9] px-4 py-3 text-sm leading-6 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15'
placeholder='What did you complete? What changed? What should we focus on next?' placeholder='What did you complete? What changed? What should we focus on next?'
/> />
<div className='mt-3 flex items-center justify-between gap-3'> <div className='mt-3 flex items-center justify-between gap-3'>
@ -365,7 +364,7 @@ const ClientPortal = () => {
</p> </p>
<button <button
type='button' type='button'
className='rounded-full bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50' className='rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
disabled={!reflection.trim()} disabled={!reflection.trim()}
onClick={saveReflection} onClick={saveReflection}
> >
@ -377,9 +376,9 @@ const ClientPortal = () => {
<div className='space-y-4'> <div className='space-y-4'>
<Panel className='overflow-hidden'> <Panel className='overflow-hidden'>
<div className='border-b border-[#19192d]/10 bg-[#fffdf9] p-4'> <div className='border-b border-[#19192d]/10 bg-[#fffdf9] p-6'>
<div className='flex items-center gap-3'> <div className='flex items-center gap-3'>
<span className='grid h-8 w-8 place-items-center rounded-full bg-[#f3fbf8] text-[#35b7a5]'> <span className='grid h-8 w-8 place-items-center rounded-none bg-[#fffdf9] text-[#35b7a5]'>
<BaseIcon <BaseIcon
path={mdiMessageReplyTextOutline} path={mdiMessageReplyTextOutline}
size={18} size={18}
@ -396,9 +395,9 @@ const ClientPortal = () => {
</div> </div>
</div> </div>
<div className='space-y-3 p-4'> <div className='space-y-3 p-6'>
{latestSession && ( {latestSession && (
<div className='rounded-lg border border-[#19192d]/10 bg-white p-4'> <div className='rounded-none border border-[#19192d]/10 bg-white p-6'>
<p className='font-semibold text-[#19192d]'> <p className='font-semibold text-[#19192d]'>
{latestSession.title} {latestSession.title}
</p> </p>
@ -410,7 +409,7 @@ const ClientPortal = () => {
{(portalClient.sessions || []).slice(1).map((session) => ( {(portalClient.sessions || []).slice(1).map((session) => (
<details <details
key={session.id} key={session.id}
className='rounded-lg border border-[#19192d]/10 bg-white p-4' className='rounded-none border border-[#19192d]/10 bg-white p-6'
> >
<summary className='cursor-pointer font-semibold text-[#19192d]'> <summary className='cursor-pointer font-semibold text-[#19192d]'>
{session.title} {session.title}
@ -424,20 +423,20 @@ const ClientPortal = () => {
</Panel> </Panel>
<Panel> <Panel>
<div className='border-b border-[#19192d]/10 p-4'> <div className='border-b border-[#19192d]/10 p-6'>
<h2 className='font-semibold text-[#19192d]'> <h2 className='font-semibold text-[#19192d]'>
Resources Resources
</h2> </h2>
</div> </div>
<div className='space-y-3 p-4'> <div className='space-y-3 p-6'>
{(portalClient.resources || []).map((resource) => ( {(portalClient.resources || []).map((resource) => (
<a <a
key={resource.id} key={resource.id}
href={resource.url} href={resource.url}
className='flex items-center justify-between gap-4 rounded-lg border border-[#19192d]/10 bg-white p-4 transition hover:bg-[#fffdf9]' className='flex items-center justify-between gap-6 rounded-none border border-[#19192d]/10 bg-white p-6 transition hover:bg-[#fffdf9]'
> >
<div className='flex gap-3'> <div className='flex gap-3'>
<span className='grid h-8 w-8 place-items-center rounded-full bg-[#fbf8f1] text-[#b17a1e]'> <span className='grid h-8 w-8 place-items-center rounded-none bg-[#fffdf9] text-[#35b7a5]'>
<BaseIcon path={mdiBookOpenVariant} size={18} /> <BaseIcon path={mdiBookOpenVariant} size={18} />
</span> </span>
<div> <div>

View File

@ -66,7 +66,7 @@ function Panel({
}) { }) {
return ( return (
<section <section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`} className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
> >
{children} {children}
</section> </section>
@ -75,7 +75,7 @@ function Panel({
function EmptyState({ label }: { label: string }) { function EmptyState({ label }: { label: string }) {
return ( return (
<p className='rounded-lg border border-dashed border-[#19192d]/10 bg-[#fffdf9] p-4 text-sm text-[#72798a]'> <p className='rounded-none border border-dashed border-[#19192d]/10 bg-[#fffdf9] p-6 text-sm text-[#72798a]'>
{label} {label}
</p> </p>
); );
@ -148,9 +148,9 @@ const Clients = () => {
</Head> </Head>
<SectionMain> <SectionMain>
<div className='mx-auto max-w-7xl'> <div className='mx-auto max-w-7xl'>
<div className='mb-4 flex flex-col justify-between gap-4 rounded-lg bg-[#19192d] p-5 text-white md:flex-row md:items-end'> <div className='mb-4 flex flex-col justify-between gap-6 rounded-none bg-[#19192d] p-7 text-white md:flex-row md:items-end'>
<div> <div>
<div className='flex items-center gap-3 text-[#b17a1e]'> <div className='flex items-center gap-3 text-[#35b7a5]'>
<BaseIcon path={mdiAccountGroup} size={18} /> <BaseIcon path={mdiAccountGroup} size={18} />
<span className='text-xs font-semibold uppercase tracking-[0.22em]'> <span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Client CRM Client CRM
@ -162,15 +162,15 @@ const Clients = () => {
sessions, and commitments. sessions, and commitments.
</p> </p>
</div> </div>
<div className='rounded-full bg-white/10 px-3 py-1.5 text-sm font-semibold text-[#fbf8f1]'> <div className='rounded-none bg-white/10 px-4 py-2 text-sm font-semibold text-[#fffdf9]'>
{clients.length} clients {clients.length} clients
</div> </div>
</div> </div>
<div className='grid gap-4 xl:grid-cols-[0.85fr_1.15fr]'> <div className='grid gap-6 xl:grid-cols-[0.85fr_1.15fr]'>
<Panel className='overflow-hidden'> <Panel className='overflow-hidden'>
<div className='border-b border-[#19192d]/10 p-5'> <div className='border-b border-[#19192d]/10 p-7'>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Coaching relationships Coaching relationships
</p> </p>
</div> </div>
@ -180,9 +180,9 @@ const Clients = () => {
key={client.id} key={client.id}
type='button' type='button'
onClick={() => selectClient(client.id)} onClick={() => selectClient(client.id)}
className={`block w-full p-5 text-left transition ${ className={`block w-full p-7 text-left transition ${
selectedClient?.id === client.id selectedClient?.id === client.id
? 'bg-[#f3fbf8]' ? 'bg-[#fffdf9]'
: 'bg-white hover:bg-[#fffdf9]' : 'bg-white hover:bg-[#fffdf9]'
}`} }`}
> >
@ -195,7 +195,7 @@ const Clients = () => {
{client.role_title} · {client.company} {client.role_title} · {client.company}
</p> </p>
</div> </div>
<span className='rounded-full bg-[#fbf8f1] px-3 py-1 text-xs font-semibold text-[#b17a1e]'> <span className='rounded-none bg-[#fffdf9] px-3 py-1 text-xs font-semibold text-[#35b7a5]'>
{client.status} {client.status}
</span> </span>
</div> </div>
@ -208,7 +208,7 @@ const Clients = () => {
.map((tag) => ( .map((tag) => (
<span <span
key={tag} key={tag}
className='rounded-full bg-white px-3 py-1 text-xs text-[#72798a]' className='rounded-none bg-white px-3 py-1 text-xs text-[#72798a]'
> >
{tag} {tag}
</span> </span>
@ -222,9 +222,9 @@ const Clients = () => {
{selectedClient && ( {selectedClient && (
<div className='space-y-6'> <div className='space-y-6'>
<Panel className='p-4'> <Panel className='p-4'>
<div className='flex flex-col justify-between gap-4 md:flex-row md:items-start'> <div className='flex flex-col justify-between gap-6 md:flex-row md:items-start'>
<div> <div>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
{selectedClient.package?.title || 'Coaching client'} {selectedClient.package?.title || 'Coaching client'}
</p> </p>
<h2 className='mt-2 text-xl font-semibold text-[#19192d]'> <h2 className='mt-2 text-xl font-semibold text-[#19192d]'>
@ -234,7 +234,7 @@ const Clients = () => {
{selectedClient.email} {selectedClient.email}
</p> </p>
</div> </div>
<div className='rounded-lg border border-[#19192d]/10 bg-[#fffdf9] p-4 md:min-w-56'> <div className='rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-6 md:min-w-56'>
<div className='flex items-center gap-2 text-sm font-semibold text-[#35b7a5]'> <div className='flex items-center gap-2 text-sm font-semibold text-[#35b7a5]'>
<BaseIcon path={mdiCalendarClock} size={18} /> <BaseIcon path={mdiCalendarClock} size={18} />
Next session Next session
@ -246,8 +246,8 @@ const Clients = () => {
</div> </div>
</div> </div>
<div className='mt-4 grid gap-4 lg:grid-cols-2'> <div className='mt-4 grid gap-6 lg:grid-cols-2'>
<div className='rounded-lg bg-[#fffdf9] p-5'> <div className='rounded-none bg-[#fffdf9] p-7'>
<div className='flex items-center gap-2 text-sm font-semibold text-[#35b7a5]'> <div className='flex items-center gap-2 text-sm font-semibold text-[#35b7a5]'>
<BaseIcon path={mdiTarget} size={18} /> <BaseIcon path={mdiTarget} size={18} />
Goals Goals
@ -256,7 +256,7 @@ const Clients = () => {
{selectedClient.goals} {selectedClient.goals}
</p> </p>
</div> </div>
<div className='rounded-lg bg-[#fffdf9] p-5'> <div className='rounded-none bg-[#fffdf9] p-7'>
<div className='flex items-center gap-2 text-sm font-semibold text-[#35b7a5]'> <div className='flex items-center gap-2 text-sm font-semibold text-[#35b7a5]'>
<BaseIcon path={mdiFileDocumentOutline} size={18} /> <BaseIcon path={mdiFileDocumentOutline} size={18} />
Private coach notes Private coach notes
@ -269,41 +269,41 @@ const Clients = () => {
</Panel> </Panel>
<Panel> <Panel>
<div className='border-b border-[#19192d]/10 p-5'> <div className='border-b border-[#19192d]/10 p-7'>
<div className='flex items-center justify-between gap-4'> <div className='flex items-center justify-between gap-6'>
<div> <div>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Next-session prep Next-session prep
</p> </p>
<h3 className='mt-2 text-lg font-semibold text-[#19192d]'> <h3 className='mt-2 text-lg font-semibold text-[#19192d]'>
Coach prep brief Coach prep brief
</h3> </h3>
</div> </div>
<span className='rounded-full bg-[#f3fbf8] px-3 py-1 text-xs font-semibold text-[#35b7a5]'> <span className='rounded-none bg-[#fffdf9] px-3 py-1 text-xs font-semibold text-[#35b7a5]'>
Ready Ready
</span> </span>
</div> </div>
</div> </div>
{latestPrepBrief ? ( {latestPrepBrief ? (
<div className='grid gap-4 p-5 lg:grid-cols-2'> <div className='grid gap-6 p-7 lg:grid-cols-2'>
<div className='rounded-lg bg-[#fffdf9] p-4'> <div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Client reflection Client reflection
</p> </p>
<div className='mt-3'> <div className='mt-3'>
<PrepText value={latestPrepBrief.client_reflection} /> <PrepText value={latestPrepBrief.client_reflection} />
</div> </div>
</div> </div>
<div className='rounded-lg bg-[#fffdf9] p-4'> <div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Open commitments Open commitments
</p> </p>
<div className='mt-3'> <div className='mt-3'>
<PrepText value={latestPrepBrief.open_commitments} /> <PrepText value={latestPrepBrief.open_commitments} />
</div> </div>
</div> </div>
<div className='rounded-lg bg-[#fffdf9] p-4'> <div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Suggested questions Suggested questions
</p> </p>
<div className='mt-3'> <div className='mt-3'>
@ -312,16 +312,16 @@ const Clients = () => {
/> />
</div> </div>
</div> </div>
<div className='rounded-lg bg-[#fffdf9] p-4'> <div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Watch points Watch points
</p> </p>
<div className='mt-3'> <div className='mt-3'>
<PrepText value={latestPrepBrief.sensitive_topics} /> <PrepText value={latestPrepBrief.sensitive_topics} />
</div> </div>
</div> </div>
<div className='rounded-lg bg-[#fffdf9] p-4 lg:col-span-2'> <div className='rounded-none bg-[#fffdf9] p-6 lg:col-span-2'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Previous summary Previous summary
</p> </p>
<div className='mt-3'> <div className='mt-3'>
@ -336,19 +336,19 @@ const Clients = () => {
)} )}
</Panel> </Panel>
<div className='grid gap-4 lg:grid-cols-2'> <div className='grid gap-6 lg:grid-cols-2'>
<Panel> <Panel>
<div className='border-b border-[#19192d]/10 p-5'> <div className='border-b border-[#19192d]/10 p-7'>
<h3 className='text-lg font-semibold text-[#19192d]'> <h3 className='text-lg font-semibold text-[#19192d]'>
Session timeline Session timeline
</h3> </h3>
</div> </div>
<div className='space-y-4 p-5'> <div className='space-y-4 p-7'>
{(selectedClient.sessions || []).length > 0 ? ( {(selectedClient.sessions || []).length > 0 ? (
(selectedClient.sessions || []).map((session) => ( (selectedClient.sessions || []).map((session) => (
<div <div
key={session.id} key={session.id}
className='rounded-lg border border-[#19192d]/10 bg-[#fffdf9] p-4' className='rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-6'
> >
<p className='font-semibold text-[#19192d]'> <p className='font-semibold text-[#19192d]'>
{session.title} {session.title}
@ -365,14 +365,14 @@ const Clients = () => {
</Panel> </Panel>
<Panel> <Panel>
<div className='border-b border-[#19192d]/10 p-5'> <div className='border-b border-[#19192d]/10 p-7'>
<h3 className='text-lg font-semibold text-[#19192d]'> <h3 className='text-lg font-semibold text-[#19192d]'>
Pre-session reflection Pre-session reflection
</h3> </h3>
</div> </div>
<div className='p-5'> <div className='p-5'>
{latestReflection ? ( {latestReflection ? (
<div className='rounded-lg border border-[#19192d]/10 bg-[#fffdf9] p-4'> <div className='rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-6'>
<p className='text-sm leading-6 text-[#72798a]'> <p className='text-sm leading-6 text-[#72798a]'>
{latestReflection.client_reflection} {latestReflection.client_reflection}
</p> </p>
@ -384,22 +384,21 @@ const Clients = () => {
</Panel> </Panel>
</div> </div>
<div className='grid gap-4 lg:grid-cols-2'> <div className='grid gap-6 lg:grid-cols-2'>
<Panel> <Panel>
<div className='border-b border-[#19192d]/10 p-5'> <div className='border-b border-[#19192d]/10 p-7'>
<h3 className='text-lg font-semibold text-[#19192d]'> <h3 className='text-lg font-semibold text-[#19192d]'>
Open commitments Open commitments
</h3> </h3>
</div> </div>
<div className='space-y-4 p-5'> <div className='space-y-4 p-7'>
{(selectedClient.action_items || []).length > 0 ? ( {(selectedClient.action_items || []).length > 0 ? (
(selectedClient.action_items || []).map((item) => ( (selectedClient.action_items || []).map((item) => (
<div <div
key={item.id} key={item.id}
className='flex gap-3 rounded-lg border border-[#19192d]/10 bg-white p-4' className='flex gap-3 rounded-none border border-[#19192d]/10 bg-white p-6'
> >
<span className='mt-0.5 grid h-8 w-8 flex-none place-items-center rounded-full bg-[#f3fbf8] text-[#35b7a5]'> <span className='mt-0.5 grid h-8 w-8 flex-none place-items-center rounded-none bg-[#fffdf9] text-[#35b7a5]'>
<BaseIcon <BaseIcon
path={mdiCheckCircleOutline} path={mdiCheckCircleOutline}
size={18} size={18}

View File

@ -81,7 +81,7 @@ function ShellCard({
}) { }) {
return ( return (
<section <section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`} className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
> >
{children} {children}
</section> </section>
@ -137,9 +137,9 @@ const Dashboard = () => {
</Head> </Head>
<SectionMain> <SectionMain>
<div className='mx-auto max-w-7xl'> <div className='mx-auto max-w-7xl'>
<div className='grid gap-4 xl:grid-cols-[1.1fr_0.9fr]'> <div className='grid gap-6 xl:grid-cols-[1.1fr_0.9fr]'>
<div className='rounded-lg bg-[#19192d] p-5 text-white'> <div className='rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#b17a1e]'> <div className='flex items-center gap-3 text-[#35b7a5]'>
<BaseIcon path={mdiViewDashboardOutline} size={18} /> <BaseIcon path={mdiViewDashboardOutline} size={18} />
<span className='text-xs font-semibold uppercase tracking-[0.22em]'> <span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Workspace overview Workspace overview
@ -156,13 +156,13 @@ const Dashboard = () => {
<div className='mt-5 flex flex-wrap gap-3'> <div className='mt-5 flex flex-wrap gap-3'>
<Link <Link
href='/session-memory' href='/session-memory'
className='rounded-full bg-[#b17a1e] px-4 py-2 text-sm font-semibold text-[#19192d]' className='rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-[#19192d]'
> >
Generate session memory Generate session memory
</Link> </Link>
<Link <Link
href='/clients' href='/clients'
className='rounded-full border border-white/25 px-4 py-2 text-sm font-semibold text-white' className='rounded-none border border-white/25 px-4 py-2 text-sm font-semibold text-white'
> >
Open client records Open client records
</Link> </Link>
@ -170,7 +170,7 @@ const Dashboard = () => {
</div> </div>
<ShellCard className='p-4'> <ShellCard className='p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Next session prep Next session prep
</p> </p>
{nextPrepBrief ? ( {nextPrepBrief ? (
@ -188,7 +188,7 @@ const Dashboard = () => {
</p> </p>
<Link <Link
href={`/clients?clientId=${nextPrepBrief.client?.id}`} href={`/clients?clientId=${nextPrepBrief.client?.id}`}
className='mt-4 inline-flex items-center gap-2 rounded-full bg-[#35b7a5] px-3 py-1.5 text-sm font-semibold text-white' className='mt-4 inline-flex items-center gap-2 rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white'
> >
Open prep Open prep
<BaseIcon path={mdiArrowRight} size={18} /> <BaseIcon path={mdiArrowRight} size={18} />
@ -204,11 +204,11 @@ const Dashboard = () => {
</ShellCard> </ShellCard>
</div> </div>
<div className='mt-4 grid gap-4 md:grid-cols-2 xl:grid-cols-4'> <div className='mt-4 grid gap-6 md:grid-cols-2 xl:grid-cols-4'>
{stats.map((stat) => ( {stats.map((stat) => (
<Link key={stat.label} href={stat.href}> <Link key={stat.label} href={stat.href}>
<ShellCard className='h-full p-5 transition'> <ShellCard className='h-full p-7 transition'>
<div className='flex items-start justify-between gap-4'> <div className='flex items-start justify-between gap-6'>
<div> <div>
<p className='text-sm font-semibold text-[#72798a]'> <p className='text-sm font-semibold text-[#72798a]'>
{stat.label} {stat.label}
@ -217,7 +217,7 @@ const Dashboard = () => {
{loading ? '...' : stat.value} {loading ? '...' : stat.value}
</p> </p>
</div> </div>
<span className='grid h-9 w-9 place-items-center rounded-full bg-[#f3fbf8] text-[#35b7a5]'> <span className='grid h-9 w-9 place-items-center rounded-none bg-[#fffdf9] text-[#35b7a5]'>
<BaseIcon path={stat.icon} size={19} /> <BaseIcon path={stat.icon} size={19} />
</span> </span>
</div> </div>
@ -226,12 +226,12 @@ const Dashboard = () => {
))} ))}
</div> </div>
<div className='mt-4 grid gap-4 xl:grid-cols-[0.95fr_1.05fr]'> <div className='mt-4 grid gap-6 xl:grid-cols-[0.95fr_1.05fr]'>
<ShellCard> <ShellCard>
<div className='border-b border-[#19192d]/10 p-4'> <div className='border-b border-[#19192d]/10 p-6'>
<div className='flex items-center justify-between gap-4'> <div className='flex items-center justify-between gap-6'>
<div> <div>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Client records Client records
</p> </p>
<h2 className='mt-2 text-lg font-semibold'> <h2 className='mt-2 text-lg font-semibold'>
@ -251,9 +251,9 @@ const Dashboard = () => {
<Link <Link
key={client.id} key={client.id}
href={`/clients?clientId=${client.id}`} href={`/clients?clientId=${client.id}`}
className='block p-5 transition hover:bg-[#fffdf9]' className='block p-7 transition hover:bg-[#fffdf9]'
> >
<div className='flex items-start justify-between gap-4'> <div className='flex items-start justify-between gap-6'>
<div> <div>
<p className='font-semibold text-[#19192d]'> <p className='font-semibold text-[#19192d]'>
{client.name} {client.name}
@ -262,7 +262,7 @@ const Dashboard = () => {
{client.role_title} · {client.company} {client.role_title} · {client.company}
</p> </p>
</div> </div>
<span className='rounded-full bg-[#fbf8f1] px-3 py-1 text-xs font-semibold text-[#b17a1e]'> <span className='rounded-none bg-[#fffdf9] px-3 py-1 text-xs font-semibold text-[#35b7a5]'>
{client.package?.title || 'Coaching'} {client.package?.title || 'Coaching'}
</span> </span>
</div> </div>
@ -272,10 +272,10 @@ const Dashboard = () => {
</ShellCard> </ShellCard>
<ShellCard> <ShellCard>
<div className='border-b border-[#19192d]/10 p-4'> <div className='border-b border-[#19192d]/10 p-6'>
<div className='flex items-center justify-between gap-4'> <div className='flex items-center justify-between gap-6'>
<div> <div>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Recent intelligence Recent intelligence
</p> </p>
<h2 className='mt-2 text-lg font-semibold'> <h2 className='mt-2 text-lg font-semibold'>
@ -309,10 +309,10 @@ const Dashboard = () => {
</div> </div>
<ShellCard className='mt-4'> <ShellCard className='mt-4'>
<div className='border-b border-[#19192d]/10 p-4'> <div className='border-b border-[#19192d]/10 p-6'>
<div className='flex items-center justify-between gap-4'> <div className='flex items-center justify-between gap-6'>
<div> <div>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Next-session prep Next-session prep
</p> </p>
<h2 className='mt-2 text-lg font-semibold'> <h2 className='mt-2 text-lg font-semibold'>
@ -332,9 +332,9 @@ const Dashboard = () => {
<Link <Link
key={brief.id} key={brief.id}
href={`/clients?clientId=${brief.client?.id}`} href={`/clients?clientId=${brief.client?.id}`}
className='block p-5 transition hover:bg-[#fffdf9]' className='block p-7 transition hover:bg-[#fffdf9]'
> >
<div className='flex items-start justify-between gap-4'> <div className='flex items-start justify-between gap-6'>
<div> <div>
<p className='font-semibold text-[#19192d]'> <p className='font-semibold text-[#19192d]'>
{brief.client?.name} {brief.client?.name}
@ -343,7 +343,7 @@ const Dashboard = () => {
{brief.client?.role_title} · {brief.client?.company} {brief.client?.role_title} · {brief.client?.company}
</p> </p>
</div> </div>
<span className='rounded-full bg-[#f3fbf8] px-3 py-1 text-xs font-semibold text-[#35b7a5]'> <span className='rounded-none bg-[#fffdf9] px-3 py-1 text-xs font-semibold text-[#35b7a5]'>
Ready Ready
</span> </span>
</div> </div>

View File

@ -7,25 +7,22 @@ import { getPageTitle } from '../config';
const ui = { const ui = {
page: 'bg-[#fffdf9] text-[#19192d]', page: 'bg-[#fffdf9] text-[#19192d]',
banner: banner: 'bg-[#19192d] text-white',
'bg-gradient-to-r from-[#35b7a5] via-[#95b76e] to-[#c38a25] text-white', navShell: 'rounded-none bg-white ring-1 ring-[#19192d]/5',
navShell:
'rounded-full bg-white shadow-[0_18px_60px_rgba(31,31,50,0.08)] ring-1 ring-[#19192d]/5',
ink: 'text-[#19192d]', ink: 'text-[#19192d]',
muted: 'text-[#72798a]', muted: 'text-[#72798a]',
accent: 'text-[#35b7a5]', accent: 'text-[#35b7a5]',
gold: 'text-[#b17a1e]', gold: 'text-[#35b7a5]',
border: 'border-[#19192d]/10', border: 'border-[#19192d]/10',
surface: 'bg-white', surface: 'bg-white',
softSurface: 'bg-[#fbf8f1]', softSurface: 'bg-[#fffdf9]',
darkPanel: 'bg-[#19192d] text-white', darkPanel: 'bg-[#19192d] text-white',
darkMuted: 'text-white/70', darkMuted: 'text-white/70',
button: button: 'bg-[#35b7a5] text-white transition hover:brightness-105',
'bg-gradient-to-r from-[#36b39f] to-[#b98624] text-white shadow-[0_18px_45px_rgba(54,179,159,0.24)] transition hover:brightness-105',
section: 'mx-auto max-w-7xl px-5 py-20 lg:px-8', section: 'mx-auto max-w-7xl px-5 py-20 lg:px-8',
card: 'rounded-[1.75rem] border border-[#19192d]/10 bg-white shadow-[0_18px_50px_rgba(31,31,50,0.05)]', card: 'rounded-none border border-[#19192d]/10 bg-white ',
softCard: 'rounded-[1.75rem] border border-[#19192d]/10 bg-[#fbf8f1]', softCard: 'rounded-none border border-[#19192d]/10 bg-[#fffdf9]',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#b17a1e]', overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#35b7a5]',
heading: 'font-serif font-semibold tracking-tight text-[#19192d]', heading: 'font-serif font-semibold tracking-tight text-[#19192d]',
}; };
@ -134,7 +131,7 @@ function Nav() {
href='/' href='/'
className='flex items-center gap-3 text-lg font-semibold tracking-tight' className='flex items-center gap-3 text-lg font-semibold tracking-tight'
> >
<span className='flex h-9 w-9 items-center justify-center rounded-xl bg-[#f3fbf8] text-xl font-black text-[#35b7a5]'> <span className='flex h-9 w-9 items-center justify-center rounded-none bg-[#fffdf9] text-xl font-black text-[#35b7a5]'>
C C
</span> </span>
<span className='sr-only'>Coaching SaaS Workspace</span> <span className='sr-only'>Coaching SaaS Workspace</span>
@ -150,7 +147,7 @@ function Nav() {
</nav> </nav>
<Link <Link
href='/intake/' href='/intake/'
className={`rounded-full px-5 py-2.5 text-sm font-semibold ${ui.button}`} className={`rounded-none px-5 py-2.5 text-sm font-semibold ${ui.button}`}
> >
Start free Start free
</Link> </Link>
@ -194,7 +191,7 @@ function Mockup({ type }: { type: string }) {
<div className={`${ui.card} p-5`}> <div className={`${ui.card} p-5`}>
<div className='flex items-center justify-between border-b border-[#19192d]/10 pb-4'> <div className='flex items-center justify-between border-b border-[#19192d]/10 pb-4'>
<p className={`${ui.overline} text-xs`}>Recording</p> <p className={`${ui.overline} text-xs`}>Recording</p>
<span className='rounded-full bg-[#e8f6f2] px-3 py-1 text-sm font-semibold text-[#248b7e]'> <span className='rounded-none bg-[#fffdf9] px-3 py-1 text-sm font-semibold text-[#35b7a5]'>
Zoom connected Zoom connected
</span> </span>
</div> </div>
@ -213,9 +210,9 @@ function Mockup({ type }: { type: string }) {
].map((item) => ( ].map((item) => (
<div <div
key={item} key={item}
className='flex items-center gap-3 rounded-2xl bg-[#fbf8f1] p-3' className='flex items-center gap-3 rounded-none bg-[#fffdf9] p-3'
> >
<span className='flex h-7 w-7 items-center justify-center rounded-full bg-[#35b7a5] text-sm text-white'> <span className='flex h-7 w-7 items-center justify-center rounded-none bg-[#35b7a5] text-sm text-white'>
</span> </span>
<span className='font-medium'>{item}</span> <span className='font-medium'>{item}</span>
@ -233,8 +230,8 @@ function Mockup({ type }: { type: string }) {
<h3 className='mt-2 text-2xl font-semibold'> <h3 className='mt-2 text-2xl font-semibold'>
Sarah Mitchell · Session 4 Sarah Mitchell · Session 4
</h3> </h3>
<div className='mt-5 rounded-2xl bg-[#fbf8f1] p-4'> <div className='mt-5 rounded-none bg-[#fffdf9] p-4'>
<p className='text-sm font-semibold text-[#b17a1e]'>Summary</p> <p className='text-sm font-semibold text-[#35b7a5]'>Summary</p>
<p className='mt-2 leading-7'> <p className='mt-2 leading-7'>
Explored over-preparing for presentations and the shift from proving Explored over-preparing for presentations and the shift from proving
competence to trusting it. competence to trusting it.
@ -244,7 +241,7 @@ function Mockup({ type }: { type: string }) {
{['Confidence', 'Delegation', 'Breakthrough'].map((item) => ( {['Confidence', 'Delegation', 'Breakthrough'].map((item) => (
<span <span
key={item} key={item}
className='rounded-full bg-[#e8f6f2] px-3 py-1 text-sm font-semibold text-[#248b7e]' className='rounded-none bg-[#fffdf9] px-3 py-1 text-sm font-semibold text-[#35b7a5]'
> >
{item} {item}
</span> </span>
@ -252,11 +249,11 @@ function Mockup({ type }: { type: string }) {
</div> </div>
<div className='mt-5 flex gap-3'> <div className='mt-5 flex gap-3'>
<button <button
className={`rounded-full px-5 py-3 font-semibold ${ui.button}`} className={`rounded-none px-5 py-3 font-semibold ${ui.button}`}
> >
Looks good Looks good
</button> </button>
<button className='rounded-full border border-[#19192d]/10 px-5 py-3 font-semibold'> <button className='rounded-none border border-[#19192d]/10 px-5 py-3 font-semibold'>
Edit Edit
</button> </button>
</div> </div>
@ -272,22 +269,22 @@ function Mockup({ type }: { type: string }) {
<span className={ui.muted}>Day 3</span> <span className={ui.muted}>Day 3</span>
</div> </div>
<div className='space-y-4'> <div className='space-y-4'>
<div className='rounded-2xl bg-[#fbf8f1] p-4'> <div className='rounded-none bg-[#fffdf9] p-4'>
<p className='text-sm font-semibold text-[#72798a]'>You sent</p> <p className='text-sm font-semibold text-[#72798a]'>You sent</p>
<p className='mt-2 leading-7'> <p className='mt-2 leading-7'>
Last session you mentioned confidence feels different in small Last session you mentioned confidence feels different in small
groups vs large meetings. What did you notice this week? groups vs large meetings. What did you notice this week?
</p> </p>
</div> </div>
<div className='ml-8 rounded-2xl bg-white p-4 ring-1 ring-[#19192d]/10'> <div className='ml-8 rounded-none bg-white p-4 ring-1 ring-[#19192d]/10'>
<p className='text-sm font-semibold'>Sarah Mitchell</p> <p className='text-sm font-semibold'>Sarah Mitchell</p>
<p className='mt-2 leading-7'> <p className='mt-2 leading-7'>
I led the Monday standup and it felt easier. I think naming it I led the Monday standup and it felt easier. I think naming it
helped. helped.
</p> </p>
</div> </div>
<div className='rounded-2xl bg-[#e8f6f2] p-4'> <div className='rounded-none bg-[#fffdf9] p-4'>
<p className='text-sm font-semibold text-[#248b7e]'> <p className='text-sm font-semibold text-[#35b7a5]'>
Coach-approved suggestion Coach-approved suggestion
</p> </p>
<p className='mt-2 leading-7'> <p className='mt-2 leading-7'>
@ -305,20 +302,20 @@ function Mockup({ type }: { type: string }) {
<p className={`${ui.overline} text-xs`}>Prep brief</p> <p className={`${ui.overline} text-xs`}>Prep brief</p>
<h3 className='mt-2 text-2xl font-semibold'>Session 5</h3> <h3 className='mt-2 text-2xl font-semibold'>Session 5</h3>
<div className='mt-5 grid gap-3'> <div className='mt-5 grid gap-3'>
<div className='rounded-2xl bg-[#fbf8f1] p-4'> <div className='rounded-none bg-[#fffdf9] p-4'>
<p className='font-semibold'>Last session themes</p> <p className='font-semibold'>Last session themes</p>
<p className={`mt-2 ${ui.muted}`}> <p className={`mt-2 ${ui.muted}`}>
Confidence · Delegation · Board presence Confidence · Delegation · Board presence
</p> </p>
</div> </div>
<div className='rounded-2xl bg-[#fbf8f1] p-4'> <div className='rounded-none bg-[#fffdf9] p-4'>
<p className='font-semibold'>Open commitments</p> <p className='font-semibold'>Open commitments</p>
<p className={`mt-2 ${ui.muted}`}> <p className={`mt-2 ${ui.muted}`}>
Lead Monday standup without notes. Delegate Q2 report. Lead Monday standup without notes. Delegate Q2 report.
</p> </p>
</div> </div>
<div className={`${ui.darkPanel} rounded-2xl p-4`}> <div className={`${ui.darkPanel} rounded-none p-4`}>
<p className='text-sm font-semibold text-[#c79a38]'> <p className='text-sm font-semibold text-[#35b7a5]'>
Suggested opening Suggested opening
</p> </p>
<p className='mt-2 leading-7'> <p className='mt-2 leading-7'>
@ -332,8 +329,8 @@ function Mockup({ type }: { type: string }) {
return ( return (
<div className={`${ui.card} p-5`}> <div className={`${ui.card} p-5`}>
<div className={`${ui.darkPanel} rounded-[1.5rem] p-5`}> <div className={`${ui.darkPanel} rounded-none p-5`}>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#c79a38]'> <p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Your coaching space Your coaching space
</p> </p>
<h3 className='mt-2 text-2xl font-semibold'>Sarah&apos;s Coaching</h3> <h3 className='mt-2 text-2xl font-semibold'>Sarah&apos;s Coaching</h3>
@ -343,7 +340,7 @@ function Mockup({ type }: { type: string }) {
{['Messages', 'Notes', 'Commitments', 'Resources'].map((item) => ( {['Messages', 'Notes', 'Commitments', 'Resources'].map((item) => (
<div <div
key={item} key={item}
className='flex items-center justify-between rounded-2xl bg-[#fbf8f1] p-4' className='flex items-center justify-between rounded-none bg-[#fffdf9] p-4'
> >
<span className='font-medium'>{item}</span> <span className='font-medium'>{item}</span>
<span className={ui.accent}></span> <span className={ui.accent}></span>
@ -371,7 +368,7 @@ function StepSection({
{step.title} {step.title}
</h2> </h2>
<p className={`mt-5 text-lg leading-8 ${ui.muted}`}>{step.copy}</p> <p className={`mt-5 text-lg leading-8 ${ui.muted}`}>{step.copy}</p>
<p className='mt-6 rounded-2xl bg-[#e8f6f2] px-5 py-4 font-semibold text-[#248b7e]'> <p className='mt-6 rounded-none bg-[#fffdf9] px-5 py-4 font-semibold text-[#35b7a5]'>
{step.proof} {step.proof}
</p> </p>
</div> </div>
@ -441,13 +438,13 @@ export default function HowItWorks() {
<div className='mt-9 flex flex-wrap justify-center gap-4'> <div className='mt-9 flex flex-wrap justify-center gap-4'>
<Link <Link
href='/intake/' href='/intake/'
className={`rounded-full px-8 py-4 font-semibold ${ui.button}`} className={`rounded-none px-8 py-4 font-semibold ${ui.button}`}
> >
Start free Start free
</Link> </Link>
<a <a
href='#coaching-week' href='#coaching-week'
className='rounded-full border border-[#19192d]/10 bg-white px-8 py-4 font-semibold' className='rounded-none border border-[#19192d]/10 bg-white px-8 py-4 font-semibold'
> >
See your coaching week See your coaching week
</a> </a>
@ -485,7 +482,7 @@ export default function HowItWorks() {
<div className='mx-auto max-w-7xl lg:px-8'> <div className='mx-auto max-w-7xl lg:px-8'>
<div className='grid grid-cols-1 gap-10 lg:grid-cols-[0.9fr_1.1fr]'> <div className='grid grid-cols-1 gap-10 lg:grid-cols-[0.9fr_1.1fr]'>
<div> <div>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#c79a38]'> <p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Go deeper Go deeper
</p> </p>
<h2 className='mt-4 font-serif text-5xl font-semibold leading-tight md:text-6xl'> <h2 className='mt-4 font-serif text-5xl font-semibold leading-tight md:text-6xl'>
@ -501,7 +498,7 @@ export default function HowItWorks() {
{deeperItems.map(([title, copy]) => ( {deeperItems.map(([title, copy]) => (
<div <div
key={title} key={title}
className='rounded-[1.5rem] border border-white/10 bg-white/5 p-6' className='rounded-none border border-white/10 bg-white/5 p-6'
> >
<h3 className='text-xl font-semibold'>{title}</h3> <h3 className='text-xl font-semibold'>{title}</h3>
<p className={`mt-3 leading-7 ${ui.darkMuted}`}>{copy}</p> <p className={`mt-3 leading-7 ${ui.darkMuted}`}>{copy}</p>
@ -518,7 +515,7 @@ export default function HowItWorks() {
<div className='grid grid-cols-1 items-center gap-10 lg:grid-cols-[0.95fr_1.05fr]'> <div className='grid grid-cols-1 items-center gap-10 lg:grid-cols-[0.95fr_1.05fr]'>
<div className={`${ui.card} overflow-hidden`}> <div className={`${ui.card} overflow-hidden`}>
<div className={`p-6 ${ui.darkPanel}`}> <div className={`p-6 ${ui.darkPanel}`}>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#c79a38]'> <p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Client view Client view
</p> </p>
<h3 className='mt-2 text-2xl font-semibold'> <h3 className='mt-2 text-2xl font-semibold'>
@ -529,20 +526,20 @@ export default function HowItWorks() {
</p> </p>
</div> </div>
<div className='grid gap-4 p-6'> <div className='grid gap-4 p-6'>
<div className='rounded-2xl bg-[#fbf8f1] p-4'> <div className='rounded-none bg-[#fffdf9] p-4'>
<p className='font-semibold'>Reflection prompt</p> <p className='font-semibold'>Reflection prompt</p>
<p className={`mt-2 leading-7 ${ui.muted}`}> <p className={`mt-2 leading-7 ${ui.muted}`}>
What is one boundary you could set this week to protect What is one boundary you could set this week to protect
strategic thinking time? strategic thinking time?
</p> </p>
</div> </div>
<div className='rounded-2xl border border-[#19192d]/10 p-4'> <div className='rounded-none border border-[#19192d]/10 p-4'>
<p className='font-semibold'>Session notes 6 shared</p> <p className='font-semibold'>Session notes 6 shared</p>
<p className={`mt-2 ${ui.muted}`}> <p className={`mt-2 ${ui.muted}`}>
Board presence, CPO conversations, delegation trust. Board presence, CPO conversations, delegation trust.
</p> </p>
</div> </div>
<div className='rounded-2xl border border-[#19192d]/10 p-4'> <div className='rounded-none border border-[#19192d]/10 p-4'>
<p className='font-semibold'>Commitments</p> <p className='font-semibold'>Commitments</p>
<p className={`mt-2 ${ui.muted}`}>2 open · 5 done</p> <p className={`mt-2 ${ui.muted}`}>2 open · 5 done</p>
</div> </div>
@ -604,10 +601,10 @@ export default function HowItWorks() {
<section id='pricing' className='px-5 py-20'> <section id='pricing' className='px-5 py-20'>
<div <div
className={`mx-auto grid max-w-7xl grid-cols-1 overflow-hidden rounded-[2rem] border lg:grid-cols-[0.9fr_1.1fr] ${ui.border} ${ui.darkPanel}`} className={`mx-auto grid max-w-7xl grid-cols-1 overflow-hidden rounded-none border lg:grid-cols-[0.9fr_1.1fr] ${ui.border} ${ui.darkPanel}`}
> >
<div className='p-8 md:p-12'> <div className='p-8 md:p-12'>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#c79a38]'> <p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Simple pricing Simple pricing
</p> </p>
<h2 className='mt-4 font-serif text-5xl font-semibold leading-tight'> <h2 className='mt-4 font-serif text-5xl font-semibold leading-tight'>
@ -625,7 +622,7 @@ export default function HowItWorks() {
</p> </p>
<Link <Link
href='/intake/' href='/intake/'
className={`mt-8 inline-flex rounded-full px-7 py-4 font-semibold ${ui.button}`} className={`mt-8 inline-flex rounded-none px-7 py-4 font-semibold ${ui.button}`}
> >
Start free Start free
</Link> </Link>
@ -655,7 +652,7 @@ export default function HowItWorks() {
</section> </section>
<section className={`px-5 py-20 text-center ${ui.darkPanel}`}> <section className={`px-5 py-20 text-center ${ui.darkPanel}`}>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#c79a38]'> <p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Ready to try it? Ready to try it?
</p> </p>
<h2 className='mx-auto mt-4 max-w-3xl font-serif text-5xl font-semibold leading-tight md:text-6xl'> <h2 className='mx-auto mt-4 max-w-3xl font-serif text-5xl font-semibold leading-tight md:text-6xl'>
@ -664,7 +661,7 @@ export default function HowItWorks() {
<div className='mt-8 flex justify-center'> <div className='mt-8 flex justify-center'>
<Link <Link
href='/intake/' href='/intake/'
className={`rounded-full px-8 py-4 font-semibold ${ui.button}`} className={`rounded-none px-8 py-4 font-semibold ${ui.button}`}
> >
Start free Start free
</Link> </Link>

View File

@ -7,25 +7,22 @@ import { getPageTitle } from '../config';
const ui = { const ui = {
page: 'bg-[#fffdf9] text-[#19192d]', page: 'bg-[#fffdf9] text-[#19192d]',
banner: banner: 'bg-[#19192d] text-white',
'bg-gradient-to-r from-[#35b7a5] via-[#95b76e] to-[#c38a25] text-white', navShell: 'rounded-none bg-white ring-1 ring-[#19192d]/5',
navShell:
'rounded-full bg-white shadow-[0_18px_60px_rgba(31,31,50,0.08)] ring-1 ring-[#19192d]/5',
ink: 'text-[#19192d]', ink: 'text-[#19192d]',
muted: 'text-[#72798a]', muted: 'text-[#72798a]',
accent: 'text-[#35b7a5]', accent: 'text-[#35b7a5]',
gold: 'text-[#b17a1e]', gold: 'text-[#35b7a5]',
border: 'border-[#19192d]/10', border: 'border-[#19192d]/10',
surface: 'bg-white', surface: 'bg-white',
softSurface: 'bg-[#fbf8f1]', softSurface: 'bg-[#fffdf9]',
darkPanel: 'bg-[#19192d] text-white', darkPanel: 'bg-[#19192d] text-white',
darkMuted: 'text-white/70', darkMuted: 'text-white/70',
button: button: 'bg-[#35b7a5] text-white transition hover:brightness-105',
'bg-gradient-to-r from-[#36b39f] to-[#b98624] text-white shadow-[0_18px_45px_rgba(54,179,159,0.24)] transition hover:brightness-105',
section: 'mx-auto max-w-7xl px-5 py-20 lg:px-8', section: 'mx-auto max-w-7xl px-5 py-20 lg:px-8',
card: 'rounded-[1.75rem] border border-[#19192d]/10 bg-white shadow-[0_18px_50px_rgba(31,31,50,0.05)]', card: 'rounded-none border border-[#19192d]/10 bg-white ',
softCard: 'rounded-[1.75rem] border border-[#19192d]/10 bg-[#fbf8f1]', softCard: 'rounded-none border border-[#19192d]/10 bg-[#fffdf9]',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#b17a1e]', overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#35b7a5]',
heading: 'font-serif font-semibold tracking-tight text-[#19192d]', heading: 'font-serif font-semibold tracking-tight text-[#19192d]',
}; };
@ -162,7 +159,7 @@ export default function Starter() {
href='/' href='/'
className='flex items-center gap-3 text-lg font-semibold tracking-tight' className='flex items-center gap-3 text-lg font-semibold tracking-tight'
> >
<span className='flex h-9 w-9 items-center justify-center rounded-xl bg-[#f3fbf8] text-xl font-black text-[#35b7a5]'> <span className='flex h-9 w-9 items-center justify-center rounded-none bg-[#fffdf9] text-xl font-black text-[#35b7a5]'>
C C
</span> </span>
<span className='sr-only'>Coaching SaaS Workspace</span> <span className='sr-only'>Coaching SaaS Workspace</span>
@ -180,7 +177,7 @@ export default function Starter() {
</nav> </nav>
<Link <Link
href='/intake/' href='/intake/'
className={`rounded-full px-5 py-2.5 text-sm font-semibold ${ui.button}`} className={`rounded-none px-5 py-2.5 text-sm font-semibold ${ui.button}`}
> >
Start free Start free
</Link> </Link>
@ -208,7 +205,7 @@ export default function Starter() {
<div className='mt-9 flex justify-center'> <div className='mt-9 flex justify-center'>
<Link <Link
href='/intake/' href='/intake/'
className={`rounded-full px-10 py-5 text-lg font-semibold ${ui.button}`} className={`rounded-none px-10 py-5 text-lg font-semibold ${ui.button}`}
> >
Start free Start free
</Link> </Link>
@ -229,21 +226,20 @@ export default function Starter() {
</div> </div>
<div className='relative mx-auto mt-12 max-w-4xl'> <div className='relative mx-auto mt-12 max-w-4xl'>
<div className='absolute -inset-12 rounded-full bg-[#35b7a5]/10 blur-3xl' />
<div <div
className={`relative rounded-[2rem] border p-4 shadow-[0_24px_80px_rgba(31,31,50,0.10)] ${ui.border} ${ui.surface}`} className={`relative rounded-none border p-4 ${ui.border} ${ui.surface}`}
> >
<div className={`rounded-[1.5rem] p-4 ${ui.darkPanel}`}> <div className={`rounded-none p-4 ${ui.darkPanel}`}>
<div className='mb-4 flex items-center justify-between'> <div className='mb-4 flex items-center justify-between'>
<div> <div>
<p className='text-xs uppercase tracking-[0.16em] text-[#c79a38]'> <p className='text-xs uppercase tracking-[0.16em] text-[#35b7a5]'>
Session insights Session insights
</p> </p>
<h2 className='mt-1 text-2xl font-semibold'> <h2 className='mt-1 text-2xl font-semibold'>
Maya Chen · Session 4 Maya Chen · Session 4
</h2> </h2>
</div> </div>
<span className='rounded-full bg-[#c79a38] px-3 py-1 text-sm font-semibold text-white'> <span className='rounded-none bg-[#35b7a5] px-3 py-1 text-sm font-semibold text-white'>
Review Review
</span> </span>
</div> </div>
@ -254,13 +250,13 @@ export default function Starter() {
'Decision rights', 'Decision rights',
'Founder visibility', 'Founder visibility',
].map((topic) => ( ].map((topic) => (
<div key={topic} className='rounded-2xl bg-white/10 p-4'> <div key={topic} className='rounded-none bg-white/10 p-4'>
<p className='text-sm font-medium text-white'>{topic}</p> <p className='text-sm font-medium text-white'>{topic}</p>
</div> </div>
))} ))}
</div> </div>
<div className='mt-4 rounded-2xl bg-white p-5 text-[#19192d]'> <div className='mt-4 rounded-none bg-white p-5 text-[#19192d]'>
<p <p
className={`text-sm font-semibold uppercase tracking-[0.14em] ${ui.gold}`} className={`text-sm font-semibold uppercase tracking-[0.14em] ${ui.gold}`}
> >
@ -277,8 +273,8 @@ export default function Starter() {
</div> </div>
<div className='mt-4 grid grid-cols-1 gap-4 lg:grid-cols-[0.9fr_1.1fr]'> <div className='mt-4 grid grid-cols-1 gap-4 lg:grid-cols-[0.9fr_1.1fr]'>
<div className='rounded-2xl bg-white/10 p-5'> <div className='rounded-none bg-white/10 p-5'>
<p className='text-sm font-semibold text-[#c79a38]'> <p className='text-sm font-semibold text-[#35b7a5]'>
Pattern Pattern
</p> </p>
<p className={`mt-2 leading-7 ${ui.darkMuted}`}> <p className={`mt-2 leading-7 ${ui.darkMuted}`}>
@ -286,8 +282,8 @@ export default function Starter() {
explicit decision boundaries. explicit decision boundaries.
</p> </p>
</div> </div>
<div className='rounded-2xl bg-white/10 p-5'> <div className='rounded-none bg-white/10 p-5'>
<p className='text-sm font-semibold text-[#c79a38]'> <p className='text-sm font-semibold text-[#35b7a5]'>
Follow-up draft Follow-up draft
</p> </p>
<p className={`mt-2 leading-7 ${ui.darkMuted}`}> <p className={`mt-2 leading-7 ${ui.darkMuted}`}>
@ -311,7 +307,7 @@ export default function Starter() {
the narrative instead of defending the roadmap. the narrative instead of defending the roadmap.
</p> </p>
<p <p
className={`mt-4 rounded-2xl p-3 text-sm font-medium ${ui.softSurface}`} className={`mt-4 rounded-none p-3 text-sm font-medium ${ui.softSurface}`}
> >
Suggested reply: What changed in the room when you led that Suggested reply: What changed in the room when you led that
way? way?
@ -350,7 +346,7 @@ export default function Starter() {
key={title} key={title}
className={`grid grid-cols-[3rem_1fr] gap-5 p-5 ${ui.card}`} className={`grid grid-cols-[3rem_1fr] gap-5 p-5 ${ui.card}`}
> >
<div className='flex h-12 w-12 items-center justify-center rounded-full bg-[#35b7a5] font-semibold text-white'> <div className='flex h-12 w-12 items-center justify-center rounded-none bg-[#35b7a5] font-semibold text-white'>
{index + 1} {index + 1}
</div> </div>
<div> <div>
@ -371,7 +367,7 @@ export default function Starter() {
> >
<div className='mx-auto grid max-w-7xl grid-cols-1 gap-10 lg:grid-cols-[0.95fr_1.05fr] lg:px-8'> <div className='mx-auto grid max-w-7xl grid-cols-1 gap-10 lg:grid-cols-[0.95fr_1.05fr] lg:px-8'>
<div className='flex flex-col justify-center'> <div className='flex flex-col justify-center'>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#c79a38]'> <p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Session memory Session memory
</p> </p>
<h2 className='mt-4 font-serif text-5xl font-semibold leading-tight md:text-6xl'> <h2 className='mt-4 font-serif text-5xl font-semibold leading-tight md:text-6xl'>
@ -391,7 +387,7 @@ export default function Starter() {
].map((item) => ( ].map((item) => (
<div <div
key={item} key={item}
className='rounded-2xl border border-white/10 bg-white/5 p-4' className='rounded-none border border-white/10 bg-white/5 p-4'
> >
<p className='font-semibold'>{item}</p> <p className='font-semibold'>{item}</p>
</div> </div>
@ -400,7 +396,7 @@ export default function Starter() {
</div> </div>
<div <div
className={`rounded-[2rem] border p-5 ${ui.border} ${ui.surface} ${ui.ink}`} className={`rounded-none border p-5 ${ui.border} ${ui.surface} ${ui.ink}`}
> >
<div <div
className={`flex flex-wrap items-center justify-between gap-4 border-b pb-5 ${ui.border}`} className={`flex flex-wrap items-center justify-between gap-4 border-b pb-5 ${ui.border}`}
@ -415,7 +411,7 @@ export default function Starter() {
Maya Chen · Session 5 Maya Chen · Session 5
</h3> </h3>
</div> </div>
<span className='rounded-full bg-[#e8f6f2] px-4 py-2 text-sm font-semibold text-[#248b7e]'> <span className='rounded-none bg-[#fffdf9] px-4 py-2 text-sm font-semibold text-[#35b7a5]'>
Ready when you are Ready when you are
</span> </span>
</div> </div>
@ -428,7 +424,7 @@ export default function Starter() {
].map(([value, label]) => ( ].map(([value, label]) => (
<div <div
key={label} key={label}
className={`rounded-2xl p-4 ${ui.softSurface}`} className={`rounded-none p-4 ${ui.softSurface}`}
> >
<p className='text-3xl font-semibold'>{value}</p> <p className='text-3xl font-semibold'>{value}</p>
<p className={`mt-1 text-sm ${ui.muted}`}>{label}</p> <p className={`mt-1 text-sm ${ui.muted}`}>{label}</p>
@ -436,7 +432,7 @@ export default function Starter() {
))} ))}
</div> </div>
<div className={`mt-5 rounded-2xl border p-5 ${ui.border}`}> <div className={`mt-5 rounded-none border p-5 ${ui.border}`}>
<p <p
className={`text-sm font-semibold uppercase tracking-[0.14em] ${ui.gold}`} className={`text-sm font-semibold uppercase tracking-[0.14em] ${ui.gold}`}
> >
@ -452,8 +448,8 @@ export default function Starter() {
</p> </p>
</div> </div>
<div className={`mt-5 rounded-2xl p-5 ${ui.darkPanel}`}> <div className={`mt-5 rounded-none p-5 ${ui.darkPanel}`}>
<p className='text-sm font-semibold text-[#c79a38]'> <p className='text-sm font-semibold text-[#35b7a5]'>
Suggested opening Suggested opening
</p> </p>
<p className='mt-3 text-xl leading-8'> <p className='mt-3 text-xl leading-8'>
@ -478,8 +474,8 @@ export default function Starter() {
</h2> </h2>
<p className={`mt-6 text-lg leading-8 ${ui.muted}`}> <p className={`mt-6 text-lg leading-8 ${ui.muted}`}>
Private notes stay private. Shared notes are approved. Private notes stay private. Shared notes are approved.
Client-facing content carries the coach&apos;s voice, not a generic Client-facing content carries the coach&apos;s voice, not a
chatbot voice. generic chatbot voice.
</p> </p>
</div> </div>
<div className='grid grid-cols-1 gap-4 md:grid-cols-2'> <div className='grid grid-cols-1 gap-4 md:grid-cols-2'>
@ -504,7 +500,7 @@ export default function Starter() {
</div> </div>
<Link <Link
href='/intake/' href='/intake/'
className={`rounded-full px-6 py-3 text-center font-semibold ${ui.button}`} className={`rounded-none px-6 py-3 text-center font-semibold ${ui.button}`}
> >
Start your workspace Start your workspace
</Link> </Link>
@ -527,10 +523,10 @@ export default function Starter() {
<section id='pricing' className='px-5 py-20'> <section id='pricing' className='px-5 py-20'>
<div <div
className={`mx-auto grid max-w-7xl grid-cols-1 overflow-hidden rounded-[2rem] border lg:grid-cols-[0.9fr_1.1fr] ${ui.border} ${ui.darkPanel}`} className={`mx-auto grid max-w-7xl grid-cols-1 overflow-hidden rounded-none border lg:grid-cols-[0.9fr_1.1fr] ${ui.border} ${ui.darkPanel}`}
> >
<div className='p-8 md:p-12'> <div className='p-8 md:p-12'>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#c79a38]'> <p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Template package Template package
</p> </p>
<h2 className='mt-4 font-serif text-5xl font-semibold leading-tight'> <h2 className='mt-4 font-serif text-5xl font-semibold leading-tight'>
@ -552,7 +548,7 @@ export default function Starter() {
].map((item) => ( ].map((item) => (
<div <div
key={item} key={item}
className={`rounded-2xl p-4 font-medium ${ui.softSurface}`} className={`rounded-none p-4 font-medium ${ui.softSurface}`}
> >
{item} {item}
</div> </div>
@ -560,7 +556,7 @@ export default function Starter() {
</div> </div>
<Link <Link
href='/intake/' href='/intake/'
className={`mt-8 inline-flex rounded-full px-7 py-4 font-semibold ${ui.button}`} className={`mt-8 inline-flex rounded-none px-7 py-4 font-semibold ${ui.button}`}
> >
Create workspace Create workspace
</Link> </Link>

View File

@ -36,7 +36,7 @@ function Panel({
}) { }) {
return ( return (
<section <section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`} className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
> >
{children} {children}
</section> </section>
@ -65,9 +65,12 @@ export default function IntakeLeads() {
async function archiveLead(leadId: string) { async function archiveLead(leadId: string) {
setUpdatingLeadId(leadId); setUpdatingLeadId(leadId);
const response = await axios.patch(`/coaching/intake-leads/${leadId}/status`, { const response = await axios.patch(
status: 'archived', `/coaching/intake-leads/${leadId}/status`,
}); {
status: 'archived',
},
);
setLeads((current) => setLeads((current) =>
current.map((lead) => { current.map((lead) => {
if (lead.id === leadId) { if (lead.id === leadId) {
@ -87,8 +90,8 @@ export default function IntakeLeads() {
</Head> </Head>
<SectionMain> <SectionMain>
<div className='mx-auto max-w-7xl'> <div className='mx-auto max-w-7xl'>
<div className='mb-4 rounded-lg bg-[#19192d] p-5 text-white'> <div className='mb-4 rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#b17a1e]'> <div className='flex items-center gap-3 text-[#35b7a5]'>
<BaseIcon path={mdiFormTextbox} size={18} /> <BaseIcon path={mdiFormTextbox} size={18} />
<span className='text-xs font-semibold uppercase tracking-[0.22em]'> <span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Intake Intake
@ -101,16 +104,16 @@ export default function IntakeLeads() {
</p> </p>
</div> </div>
<div className='grid gap-4'> <div className='grid gap-6'>
{leads.map((lead) => ( {leads.map((lead) => (
<Panel key={lead.id} className='p-5'> <Panel key={lead.id} className='p-5'>
<div className='flex flex-col justify-between gap-4 lg:flex-row lg:items-start'> <div className='flex flex-col justify-between gap-6 lg:flex-row lg:items-start'>
<div> <div>
<div className='flex flex-wrap items-center gap-3'> <div className='flex flex-wrap items-center gap-3'>
<h2 className='text-lg font-semibold text-[#19192d]'> <h2 className='text-lg font-semibold text-[#19192d]'>
{lead.name} {lead.name}
</h2> </h2>
<span className='rounded-full bg-[#fbf8f1] px-3 py-1 text-xs font-semibold text-[#b17a1e]'> <span className='rounded-none bg-[#fffdf9] px-3 py-1 text-xs font-semibold text-[#35b7a5]'>
{lead.status} {lead.status}
</span> </span>
</div> </div>
@ -133,7 +136,7 @@ export default function IntakeLeads() {
type='button' type='button'
disabled={updatingLeadId === lead.id} disabled={updatingLeadId === lead.id}
onClick={() => convertLead(lead.id)} onClick={() => convertLead(lead.id)}
className='inline-flex items-center gap-2 rounded-full bg-[#35b7a5] px-3 py-1.5 text-sm font-semibold text-white disabled:opacity-50' className='inline-flex items-center gap-2 rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
> >
<BaseIcon path={mdiAccountConvertOutline} size={18} /> <BaseIcon path={mdiAccountConvertOutline} size={18} />
Convert to client Convert to client
@ -144,7 +147,7 @@ export default function IntakeLeads() {
type='button' type='button'
disabled={updatingLeadId === lead.id} disabled={updatingLeadId === lead.id}
onClick={() => archiveLead(lead.id)} onClick={() => archiveLead(lead.id)}
className='inline-flex items-center gap-2 rounded-full border border-[#19192d]/10 bg-white px-3 py-1.5 text-sm font-semibold text-[#19192d] disabled:opacity-50' className='inline-flex items-center gap-2 rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d] disabled:opacity-50'
> >
<BaseIcon path={mdiArchiveOutline} size={18} /> <BaseIcon path={mdiArchiveOutline} size={18} />
Archive Archive
@ -153,25 +156,25 @@ export default function IntakeLeads() {
</div> </div>
</div> </div>
<div className='mt-5 grid gap-4 lg:grid-cols-3'> <div className='mt-5 grid gap-6 lg:grid-cols-3'>
<div className='rounded-lg bg-[#fffdf9] p-4'> <div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Goal Goal
</p> </p>
<p className='mt-3 text-sm leading-6 text-[#72798a]'> <p className='mt-3 text-sm leading-6 text-[#72798a]'>
{lead.goal || 'No goal provided.'} {lead.goal || 'No goal provided.'}
</p> </p>
</div> </div>
<div className='rounded-lg bg-[#fffdf9] p-4'> <div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Challenge Challenge
</p> </p>
<p className='mt-3 text-sm leading-6 text-[#72798a]'> <p className='mt-3 text-sm leading-6 text-[#72798a]'>
{lead.challenge || 'No challenge provided.'} {lead.challenge || 'No challenge provided.'}
</p> </p>
</div> </div>
<div className='rounded-lg bg-[#fffdf9] p-4'> <div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Desired outcome Desired outcome
</p> </p>
<p className='mt-3 text-sm leading-6 text-[#72798a]'> <p className='mt-3 text-sm leading-6 text-[#72798a]'>

View File

@ -6,7 +6,7 @@ import LayoutGuest from '../layouts/Guest';
import { getPageTitle } from '../config'; import { getPageTitle } from '../config';
const fieldClass = const fieldClass =
'mt-2 w-full rounded-lg border border-[#19192d]/10 bg-white px-3 py-2 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15'; 'mt-2 w-full rounded-none border border-[#19192d]/10 bg-white px-4 py-3 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15';
type IntakeValues = { type IntakeValues = {
name: string; name: string;
@ -83,7 +83,7 @@ export default function Intake() {
</Link> </Link>
<Link <Link
href='/login/' href='/login/'
className='rounded-full border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold' className='rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold'
> >
Login Login
</Link> </Link>
@ -92,22 +92,21 @@ export default function Intake() {
<section className='mx-auto grid max-w-6xl gap-8 px-5 py-10 lg:grid-cols-[0.85fr_1.15fr]'> <section className='mx-auto grid max-w-6xl gap-8 px-5 py-10 lg:grid-cols-[0.85fr_1.15fr]'>
<div> <div>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Coaching intake Coaching intake
</p> </p>
<h1 className='mt-4 font-serif text-5xl font-semibold leading-tight md:text-6xl'> <h1 className='mt-4 font-serif text-5xl font-semibold leading-tight md:text-6xl'>
Start with the coaching context that matters. Start with the coaching context that matters.
</h1> </h1>
<p className='mt-5 max-w-xl text-lg leading-8 text-[#72798a]'> <p className='mt-5 max-w-xl text-lg leading-8 text-[#72798a]'>
Share what you want to work on. Your coach can review this, Share what you want to work on. Your coach can review this, create
create a client record, and prepare the first session around your a client record, and prepare the first session around your goals.
goals.
</p> </p>
</div> </div>
<div className='rounded-lg border border-[#19192d]/10 bg-white p-5'> <div className='rounded-none border border-[#19192d]/10 bg-white p-7'>
{isSubmitted ? ( {isSubmitted ? (
<div className='rounded-lg bg-[#f3fbf8] p-5'> <div className='rounded-none bg-[#fffdf9] p-7'>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Received Received
</p> </p>
@ -120,7 +119,7 @@ export default function Intake() {
</div> </div>
) : ( ) : (
<form className='space-y-4' onSubmit={submitIntake}> <form className='space-y-4' onSubmit={submitIntake}>
<div className='grid gap-4 md:grid-cols-2'> <div className='grid gap-6 md:grid-cols-2'>
<FieldLabel label='Name'> <FieldLabel label='Name'>
<input <input
required required
@ -144,7 +143,7 @@ export default function Intake() {
</FieldLabel> </FieldLabel>
</div> </div>
<div className='grid gap-4 md:grid-cols-2'> <div className='grid gap-6 md:grid-cols-2'>
<FieldLabel label='Company'> <FieldLabel label='Company'>
<input <input
value={values.company} value={values.company}
@ -170,7 +169,9 @@ export default function Intake() {
required required
rows={4} rows={4}
value={values.goal} value={values.goal}
onChange={(event) => updateValue('goal', event.target.value)} onChange={(event) =>
updateValue('goal', event.target.value)
}
className={fieldClass} className={fieldClass}
/> />
</FieldLabel> </FieldLabel>
@ -197,7 +198,7 @@ export default function Intake() {
/> />
</FieldLabel> </FieldLabel>
<label className='flex gap-3 rounded-lg bg-[#fbf8f1] p-4 text-sm leading-6 text-[#72798a]'> <label className='flex gap-3 rounded-none bg-[#fffdf9] p-6 text-sm leading-6 text-[#72798a]'>
<input <input
type='checkbox' type='checkbox'
checked={values.consent_ai_notes} checked={values.consent_ai_notes}
@ -213,7 +214,7 @@ export default function Intake() {
<button <button
type='submit' type='submit'
disabled={isSubmitting} disabled={isSubmitting}
className='rounded-full bg-[#35b7a5] px-5 py-2.5 text-sm font-semibold text-white disabled:opacity-50' className='rounded-none bg-[#35b7a5] px-5 py-2.5 text-sm font-semibold text-white disabled:opacity-50'
> >
{isSubmitting ? 'Submitting...' : 'Send intake'} {isSubmitting ? 'Submitting...' : 'Send intake'}
</button> </button>

View File

@ -14,22 +14,19 @@ import { useAppDispatch, useAppSelector } from '../stores/hooks';
const ui = { const ui = {
page: 'bg-[#fffdf9] text-[#19192d]', page: 'bg-[#fffdf9] text-[#19192d]',
banner: banner: 'bg-[#19192d] text-white',
'bg-gradient-to-r from-[#35b7a5] via-[#95b76e] to-[#c38a25] text-white', navShell: 'rounded-none bg-white ring-1 ring-[#19192d]/5',
navShell:
'rounded-full bg-white shadow-[0_18px_60px_rgba(31,31,50,0.08)] ring-1 ring-[#19192d]/5',
ink: 'text-[#19192d]', ink: 'text-[#19192d]',
muted: 'text-[#72798a]', muted: 'text-[#72798a]',
accent: 'text-[#35b7a5]', accent: 'text-[#35b7a5]',
gold: 'text-[#b17a1e]', gold: 'text-[#35b7a5]',
border: 'border-[#19192d]/10', border: 'border-[#19192d]/10',
surface: 'bg-white', surface: 'bg-white',
softSurface: 'bg-[#fbf8f1]', softSurface: 'bg-[#fffdf9]',
darkPanel: 'bg-[#19192d] text-white', darkPanel: 'bg-[#19192d] text-white',
button: button: 'bg-[#35b7a5] text-white transition hover:brightness-105',
'bg-gradient-to-r from-[#36b39f] to-[#b98624] text-white shadow-[0_18px_45px_rgba(54,179,159,0.24)] transition hover:brightness-105', card: 'rounded-none border border-[#19192d]/10 bg-white ',
card: 'rounded-[1.75rem] border border-[#19192d]/10 bg-white shadow-[0_18px_50px_rgba(31,31,50,0.05)]', overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#35b7a5]',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#b17a1e]',
heading: 'font-serif font-semibold tracking-tight text-[#19192d]', heading: 'font-serif font-semibold tracking-tight text-[#19192d]',
}; };
@ -70,7 +67,7 @@ function Nav() {
href='/' href='/'
className='flex items-center gap-3 text-lg font-semibold tracking-tight' className='flex items-center gap-3 text-lg font-semibold tracking-tight'
> >
<span className='flex h-9 w-9 items-center justify-center rounded-xl bg-[#f3fbf8] text-xl font-black text-[#35b7a5]'> <span className='flex h-9 w-9 items-center justify-center rounded-none bg-[#fffdf9] text-xl font-black text-[#35b7a5]'>
C C
</span> </span>
<span className='sr-only'>Coaching SaaS Workspace</span> <span className='sr-only'>Coaching SaaS Workspace</span>
@ -85,7 +82,7 @@ function Nav() {
</nav> </nav>
<Link <Link
href='/intake/' href='/intake/'
className={`rounded-full px-5 py-2.5 text-sm font-semibold ${ui.button}`} className={`rounded-none px-5 py-2.5 text-sm font-semibold ${ui.button}`}
> >
Start free Start free
</Link> </Link>
@ -218,7 +215,7 @@ export default function Login() {
<button <button
key={account.email} key={account.email}
type='button' type='button'
className='rounded-2xl border border-[#19192d]/10 bg-[#fbf8f1] px-3 py-3 text-left transition hover:border-[#35b7a5] hover:bg-[#f3fbf8]' className='rounded-none border border-[#19192d]/10 bg-[#fffdf9] px-3 py-3 text-left transition hover:border-[#35b7a5] hover:bg-[#fffdf9]'
onClick={() => onClick={() =>
setValues({ setValues({
email: account.email, email: account.email,
@ -245,7 +242,7 @@ export default function Login() {
<Field <Field
name='email' name='email'
type='email' type='email'
className={`w-full rounded-2xl border px-4 py-3 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`} className={`w-full rounded-none border px-4 py-3 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`}
/> />
</label> </label>
@ -257,7 +254,7 @@ export default function Login() {
<Field <Field
name='password' name='password'
type={showPassword ? 'text' : 'password'} type={showPassword ? 'text' : 'password'}
className={`w-full rounded-2xl border px-4 py-3 pr-12 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`} className={`w-full rounded-none border px-4 py-3 pr-12 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`}
/> />
<button <button
type='button' type='button'
@ -286,7 +283,7 @@ export default function Login() {
</label> </label>
<Link <Link
href='/forgot' href='/forgot'
className='font-semibold text-[#248b7e] hover:underline' className='font-semibold text-[#35b7a5] hover:underline'
> >
Forgot password? Forgot password?
</Link> </Link>
@ -295,7 +292,7 @@ export default function Login() {
<button <button
type='submit' type='submit'
disabled={isFetching} disabled={isFetching}
className={`w-full rounded-full px-6 py-4 font-semibold disabled:cursor-not-allowed disabled:opacity-60 ${ui.button}`} className={`w-full rounded-none px-6 py-4 font-semibold disabled:cursor-not-allowed disabled:opacity-60 ${ui.button}`}
> >
{isFetching ? 'Opening...' : 'Login'} {isFetching ? 'Opening...' : 'Login'}
</button> </button>
@ -307,7 +304,7 @@ export default function Login() {
Don&apos;t have an account yet?{' '} Don&apos;t have an account yet?{' '}
<Link <Link
href='/register' href='/register'
className='font-semibold text-[#248b7e] hover:underline' className='font-semibold text-[#35b7a5] hover:underline'
> >
Create one Create one
</Link> </Link>

View File

@ -45,7 +45,7 @@ function Panel({
}) { }) {
return ( return (
<section <section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`} className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
> >
{children} {children}
</section> </section>
@ -70,7 +70,7 @@ function FieldWrap({
} }
const inputClassName = const inputClassName =
'w-full rounded-lg border border-[#19192d]/10 bg-[#fffdf9] px-3 py-2 text-sm text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15 disabled:bg-[#fbf8f1] disabled:text-[#72798a]'; 'w-full rounded-none border border-[#19192d]/10 bg-[#fffdf9] px-4 py-3 text-sm text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15 disabled:bg-[#fffdf9] disabled:text-[#72798a]';
const EditUsers = () => { const EditUsers = () => {
const { currentUser } = useAppSelector((state) => state.auth); const { currentUser } = useAppSelector((state) => state.auth);
@ -106,8 +106,8 @@ const EditUsers = () => {
</Head> </Head>
<main className='mx-auto max-w-7xl px-6 py-6'> <main className='mx-auto max-w-7xl px-6 py-6'>
<div className='mb-4 rounded-lg bg-[#19192d] p-5 text-white'> <div className='mb-4 rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#b17a1e]'> <div className='flex items-center gap-3 text-[#35b7a5]'>
<span className='text-lg'></span> <span className='text-lg'></span>
<span className='text-xs font-semibold uppercase tracking-[0.22em]'> <span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Account Account
@ -129,7 +129,7 @@ const EditUsers = () => {
<div className='grid gap-5 xl:grid-cols-[180px_1fr]'> <div className='grid gap-5 xl:grid-cols-[180px_1fr]'>
<div> <div>
<p className='text-sm font-semibold text-[#19192d]'>Avatar</p> <p className='text-sm font-semibold text-[#19192d]'>Avatar</p>
<div className='mt-3 flex h-32 w-32 items-center justify-center overflow-hidden rounded-full border border-[#19192d]/10 bg-[#f3fbf8]'> <div className='mt-3 flex h-32 w-32 items-center justify-center overflow-hidden rounded-none border border-[#19192d]/10 bg-[#fffdf9]'>
{avatarUrl ? ( {avatarUrl ? (
<Image <Image
className='h-full w-full object-cover object-center' className='h-full w-full object-cover object-center'
@ -164,7 +164,7 @@ const EditUsers = () => {
</div> </div>
</div> </div>
<div className='grid gap-4 md:grid-cols-2 xl:grid-cols-3'> <div className='grid gap-6 md:grid-cols-2 xl:grid-cols-3'>
<FieldWrap label='First name'> <FieldWrap label='First name'>
<Field <Field
className={inputClassName} className={inputClassName}
@ -232,20 +232,20 @@ const EditUsers = () => {
<div className='flex flex-wrap justify-end gap-3 border-t border-[#19192d]/10 pt-5'> <div className='flex flex-wrap justify-end gap-3 border-t border-[#19192d]/10 pt-5'>
<button <button
type='button' type='button'
className='rounded-full border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]' className='rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]'
onClick={() => router.push('/users/users-list')} onClick={() => router.push('/users/users-list')}
> >
Cancel Cancel
</button> </button>
<button <button
type='reset' type='reset'
className='rounded-full border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]' className='rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]'
> >
Reset Reset
</button> </button>
<button <button
type='submit' type='submit'
className='rounded-full bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white' className='rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white'
> >
Save profile Save profile
</button> </button>

View File

@ -11,18 +11,15 @@ import { getPageTitle } from '../config';
const ui = { const ui = {
page: 'bg-[#fffdf9] text-[#19192d]', page: 'bg-[#fffdf9] text-[#19192d]',
banner: banner: 'bg-[#19192d] text-white',
'bg-gradient-to-r from-[#35b7a5] via-[#95b76e] to-[#c38a25] text-white', navShell: 'rounded-none bg-white ring-1 ring-[#19192d]/5',
navShell:
'rounded-full bg-white shadow-[0_18px_60px_rgba(31,31,50,0.08)] ring-1 ring-[#19192d]/5',
ink: 'text-[#19192d]', ink: 'text-[#19192d]',
muted: 'text-[#72798a]', muted: 'text-[#72798a]',
accent: 'text-[#35b7a5]', accent: 'text-[#35b7a5]',
border: 'border-[#19192d]/10', border: 'border-[#19192d]/10',
button: button: 'bg-[#35b7a5] text-white transition hover:brightness-105',
'bg-gradient-to-r from-[#36b39f] to-[#b98624] text-white shadow-[0_18px_45px_rgba(54,179,159,0.24)] transition hover:brightness-105', card: 'rounded-none border border-[#19192d]/10 bg-white ',
card: 'rounded-[1.75rem] border border-[#19192d]/10 bg-white shadow-[0_18px_50px_rgba(31,31,50,0.05)]', overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#35b7a5]',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#b17a1e]',
heading: 'font-serif font-semibold tracking-tight text-[#19192d]', heading: 'font-serif font-semibold tracking-tight text-[#19192d]',
}; };
@ -42,7 +39,7 @@ function Nav() {
href='/' href='/'
className='flex items-center gap-3 text-lg font-semibold tracking-tight' className='flex items-center gap-3 text-lg font-semibold tracking-tight'
> >
<span className='flex h-9 w-9 items-center justify-center rounded-xl bg-[#f3fbf8] text-xl font-black text-[#35b7a5]'> <span className='flex h-9 w-9 items-center justify-center rounded-none bg-[#fffdf9] text-xl font-black text-[#35b7a5]'>
C C
</span> </span>
<span className='sr-only'>Coaching SaaS Workspace</span> <span className='sr-only'>Coaching SaaS Workspace</span>
@ -57,7 +54,7 @@ function Nav() {
</nav> </nav>
<Link <Link
href='/login/' href='/login/'
className='rounded-full border border-[#19192d]/10 bg-white px-5 py-2.5 text-sm font-semibold' className='rounded-none border border-[#19192d]/10 bg-white px-5 py-2.5 text-sm font-semibold'
> >
Login Login
</Link> </Link>
@ -188,7 +185,7 @@ export default function Register() {
<Field <Field
type='email' type='email'
name='email' name='email'
className={`w-full rounded-2xl border px-4 py-3 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`} className={`w-full rounded-none border px-4 py-3 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`}
/> />
</label> </label>
@ -199,7 +196,7 @@ export default function Register() {
<Field <Field
type='password' type='password'
name='password' name='password'
className={`w-full rounded-2xl border px-4 py-3 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`} className={`w-full rounded-none border px-4 py-3 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`}
/> />
</label> </label>
@ -210,14 +207,14 @@ export default function Register() {
<Field <Field
type='password' type='password'
name='confirm' name='confirm'
className={`w-full rounded-2xl border px-4 py-3 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`} className={`w-full rounded-none border px-4 py-3 outline-none transition focus:border-[#35b7a5] focus:ring-4 focus:ring-[#35b7a5]/10 ${ui.border}`}
/> />
</label> </label>
<button <button
type='submit' type='submit'
disabled={loading} disabled={loading}
className={`w-full rounded-full px-6 py-4 font-semibold disabled:cursor-not-allowed disabled:opacity-60 ${ui.button}`} className={`w-full rounded-none px-6 py-4 font-semibold disabled:cursor-not-allowed disabled:opacity-60 ${ui.button}`}
> >
{loading ? 'Creating...' : 'Create account'} {loading ? 'Creating...' : 'Create account'}
</button> </button>
@ -228,7 +225,7 @@ export default function Register() {
Already have an account?{' '} Already have an account?{' '}
<Link <Link
href='/login' href='/login'
className='font-semibold text-[#248b7e] hover:underline' className='font-semibold text-[#35b7a5] hover:underline'
> >
Login Login
</Link> </Link>

View File

@ -5,6 +5,7 @@ import {
mdiFileDocumentEditOutline, mdiFileDocumentEditOutline,
mdiLightbulbOnOutline, mdiLightbulbOnOutline,
mdiMicrophoneOutline, mdiMicrophoneOutline,
mdiStopCircleOutline,
mdiSendOutline, mdiSendOutline,
} from '@mdi/js'; } from '@mdi/js';
import axios from 'axios'; import axios from 'axios';
@ -53,7 +54,7 @@ function Panel({
}) { }) {
return ( return (
<section <section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`} className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
> >
{children} {children}
</section> </section>
@ -73,14 +74,14 @@ function TextField({
}) { }) {
return ( return (
<label className='block'> <label className='block'>
<span className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <span className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
{label} {label}
</span> </span>
<textarea <textarea
value={value} value={value}
rows={rows} rows={rows}
onChange={(event) => onChange(event.target.value)} onChange={(event) => onChange(event.target.value)}
className='mt-2 w-full rounded-lg border border-[#19192d]/10 bg-[#fffdf9] px-3 py-2 text-sm leading-6 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15' className='mt-2 w-full rounded-none border border-[#19192d]/10 bg-[#fffdf9] px-4 py-3 text-sm leading-6 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15'
/> />
</label> </label>
); );
@ -91,10 +92,8 @@ function StatusPill({ status }: { status?: string }) {
return ( return (
<span <span
className={`rounded-full px-3 py-1 text-xs font-semibold ${ className={`rounded-none px-3 py-1 text-xs font-semibold ${
isShared isShared ? 'bg-[#fffdf9] text-[#35b7a5]' : 'bg-[#fffdf9] text-[#35b7a5]'
? 'bg-[#f3fbf8] text-[#35b7a5]'
: 'bg-[#fbf8f1] text-[#b17a1e]'
}`} }`}
> >
{isShared ? 'Shared' : 'Coach draft'} {isShared ? 'Shared' : 'Coach draft'}
@ -147,13 +146,17 @@ const SessionMemory = () => {
const [transcript, setTranscript] = React.useState(''); const [transcript, setTranscript] = React.useState('');
const [draft, setDraft] = React.useState<MemoryDraft>(emptyDraft); const [draft, setDraft] = React.useState<MemoryDraft>(emptyDraft);
const [audioFile, setAudioFile] = React.useState<File | null>(null); const [audioFile, setAudioFile] = React.useState<File | null>(null);
const [isRecording, setIsRecording] = React.useState(false);
const [recordingSeconds, setRecordingSeconds] = React.useState(0);
const [isGenerating, setIsGenerating] = React.useState(false); const [isGenerating, setIsGenerating] = React.useState(false);
const [isTranscribing, setIsTranscribing] = React.useState(false); const [isTranscribing, setIsTranscribing] = React.useState(false);
const [isSaving, setIsSaving] = React.useState(false); const [isSaving, setIsSaving] = React.useState(false);
const [notice, setNotice] = React.useState(''); const [notice, setNotice] = React.useState('');
const [lastSavedSession, setLastSavedSession] = React.useState<Session | null>( const [lastSavedSession, setLastSavedSession] =
null, React.useState<Session | null>(null);
); const mediaRecorderRef = React.useRef<MediaRecorder | null>(null);
const mediaStreamRef = React.useRef<MediaStream | null>(null);
const audioChunksRef = React.useRef<Blob[]>([]);
async function loadData() { async function loadData() {
const [clientsResponse, sessionsResponse] = await Promise.all([ const [clientsResponse, sessionsResponse] = await Promise.all([
@ -172,6 +175,26 @@ const SessionMemory = () => {
loadData(); loadData();
}, []); }, []);
React.useEffect(() => {
if (!isRecording) {
return;
}
const intervalId = window.setInterval(() => {
setRecordingSeconds((current) => current + 1);
}, 1000);
return () => {
window.clearInterval(intervalId);
};
}, [isRecording]);
React.useEffect(() => {
return () => {
stopAudioTracks();
};
}, []);
function updateDraft(field: keyof MemoryDraft, value: string) { function updateDraft(field: keyof MemoryDraft, value: string) {
setDraft((current) => { setDraft((current) => {
return { return {
@ -223,7 +246,9 @@ const SessionMemory = () => {
}, },
); );
setTranscript(response.data.text || ''); setTranscript(response.data.text || '');
setNotice('Audio transcribed. Review the transcript before generating memory.'); setNotice(
'Audio transcribed. Review the transcript before generating memory.',
);
} catch (error) { } catch (error) {
setNotice(requestErrorMessage(error, 'Audio transcription failed.')); setNotice(requestErrorMessage(error, 'Audio transcription failed.'));
} finally { } finally {
@ -231,6 +256,102 @@ const SessionMemory = () => {
} }
} }
function stopAudioTracks() {
if (!mediaStreamRef.current) {
return;
}
mediaStreamRef.current.getTracks().forEach((track) => {
track.stop();
});
mediaStreamRef.current = null;
}
function recordedAudioType() {
if (MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) {
return 'audio/webm;codecs=opus';
}
if (MediaRecorder.isTypeSupported('audio/webm')) {
return 'audio/webm';
}
return '';
}
async function startRecording() {
if (typeof MediaRecorder === 'undefined') {
setNotice('Audio recording is not supported in this browser.');
return;
}
if (!navigator.mediaDevices?.getUserMedia) {
setNotice('Audio recording is not supported in this browser.');
return;
}
let stream: MediaStream;
try {
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
} catch (error) {
setNotice('Microphone access was blocked or failed.');
return;
}
const mimeType = recordedAudioType();
const options = mimeType ? { mimeType } : undefined;
const recorder = new MediaRecorder(stream, options);
audioChunksRef.current = [];
mediaStreamRef.current = stream;
mediaRecorderRef.current = recorder;
recorder.ondataavailable = (event) => {
if (event.data.size > 0) {
audioChunksRef.current.push(event.data);
}
};
recorder.onstop = () => {
const type = recorder.mimeType || 'audio/webm';
const blob = new Blob(audioChunksRef.current, { type });
const file = new File([blob], `session-recording-${Date.now()}.webm`, {
type,
});
setAudioFile(file);
setNotice('Recording saved. Transcribe it when you are ready.');
setIsRecording(false);
stopAudioTracks();
};
setRecordingSeconds(0);
setAudioFile(null);
setNotice('');
setIsRecording(true);
recorder.start();
}
function stopRecording() {
if (!mediaRecorderRef.current) {
return;
}
if (mediaRecorderRef.current.state !== 'inactive') {
mediaRecorderRef.current.stop();
}
}
function recordingDuration() {
const minutes = Math.floor(recordingSeconds / 60)
.toString()
.padStart(2, '0');
const seconds = (recordingSeconds % 60).toString().padStart(2, '0');
return `${minutes}:${seconds}`;
}
async function saveMemory(shareWithClient: boolean) { async function saveMemory(shareWithClient: boolean) {
setIsSaving(true); setIsSaving(true);
const response = await axios.post('/coaching/session-memory/save', { const response = await axios.post('/coaching/session-memory/save', {
@ -253,9 +374,12 @@ const SessionMemory = () => {
} }
async function shareSession(session: Session) { async function shareSession(session: Session) {
const response = await axios.patch(`/coaching/sessions/${session.id}/share`, { const response = await axios.patch(
shared_client_notes: session.shared_client_notes, `/coaching/sessions/${session.id}/share`,
}); {
shared_client_notes: session.shared_client_notes,
},
);
setSessions((current) => setSessions((current) =>
current.map((currentSession) => { current.map((currentSession) => {
@ -289,8 +413,8 @@ const SessionMemory = () => {
</Head> </Head>
<SectionMain> <SectionMain>
<div className='mx-auto max-w-7xl'> <div className='mx-auto max-w-7xl'>
<div className='mb-4 rounded-lg bg-[#19192d] p-5 text-white'> <div className='mb-4 rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#b17a1e]'> <div className='flex items-center gap-3 text-[#35b7a5]'>
<BaseIcon path={mdiFileDocumentEditOutline} size={18} /> <BaseIcon path={mdiFileDocumentEditOutline} size={18} />
<span className='text-xs font-semibold uppercase tracking-[0.22em]'> <span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Session Memory Session Memory
@ -307,27 +431,27 @@ const SessionMemory = () => {
</div> </div>
{notice && ( {notice && (
<div className='mb-4 rounded-lg border border-[#35b7a5]/20 bg-[#f3fbf8] px-4 py-3 text-sm font-semibold text-[#257f73]'> <div className='mb-4 rounded-none border border-[#35b7a5]/20 bg-[#fffdf9] px-4 py-3 text-sm font-semibold text-[#35b7a5]'>
{notice} {notice}
</div> </div>
)} )}
<div className='grid gap-4 xl:grid-cols-[0.8fr_1.2fr]'> <div className='grid gap-6 xl:grid-cols-[0.8fr_1.2fr]'>
<Panel className='p-4'> <Panel className='p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Raw session input Raw session input
</p> </p>
<h2 className='mt-2 text-lg font-semibold text-[#19192d]'> <h2 className='mt-2 text-lg font-semibold text-[#19192d]'>
Extract a session Extract a session
</h2> </h2>
<label className='mb-2 mt-4 block text-sm font-semibold text-[#72798a]'> <label className='mb-2 mt-6 block text-sm font-semibold text-[#72798a]'>
Client Client
</label> </label>
<select <select
value={clientId} value={clientId}
onChange={(event) => setClientId(event.target.value)} onChange={(event) => setClientId(event.target.value)}
className='w-full rounded-lg border border-[#19192d]/10 bg-white px-3 py-2 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15' className='w-full rounded-none border border-[#19192d]/10 bg-white px-4 py-3 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15'
> >
{clients.map((client) => ( {clients.map((client) => (
<option key={client.id} value={client.id}> <option key={client.id} value={client.id}>
@ -336,16 +460,50 @@ const SessionMemory = () => {
))} ))}
</select> </select>
<div className='mt-5 rounded-lg border border-[#19192d]/10 bg-[#fffdf9] p-3'> <div className='mt-5 rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-3'>
<div className='flex items-center gap-2 text-sm font-semibold text-[#19192d]'> <div className='flex items-center gap-2 text-sm font-semibold text-[#19192d]'>
<BaseIcon path={mdiMicrophoneOutline} size={18} /> <BaseIcon path={mdiMicrophoneOutline} size={18} />
Audio transcription Audio transcription
</div> </div>
<label className='mt-3 flex cursor-pointer items-center justify-between gap-3 rounded-lg border border-dashed border-[#19192d]/15 bg-white px-3 py-3 text-sm text-[#72798a]'> <div className='mt-4 border border-[#19192d]/10 bg-white p-4'>
<div className='flex flex-col gap-4 md:flex-row md:items-center md:justify-between'>
<div>
<p className='text-sm font-semibold text-[#19192d]'>
Record audio
</p>
<p className='mt-1 text-sm text-[#72798a]'>
{isRecording
? `Recording ${recordingDuration()}`
: 'Use your microphone and transcribe the recording below.'}
</p>
</div>
{isRecording ? (
<button
type='button'
className='inline-flex items-center justify-center gap-2 rounded-none bg-[#19192d] px-4 py-2 text-sm font-semibold text-white'
onClick={stopRecording}
>
<BaseIcon path={mdiStopCircleOutline} size={18} />
Stop recording
</button>
) : (
<button
type='button'
className='inline-flex items-center justify-center gap-2 rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
disabled={isTranscribing}
onClick={startRecording}
>
<BaseIcon path={mdiMicrophoneOutline} size={18} />
Start recording
</button>
)}
</div>
</div>
<label className='mt-3 flex cursor-pointer items-center justify-between gap-3 rounded-none border border-dashed border-[#19192d]/15 bg-white px-4 py-4 text-sm text-[#72798a]'>
<span className='truncate'> <span className='truncate'>
{audioFile ? audioFile.name : 'Choose an audio file'} {audioFile ? audioFile.name : 'Choose an audio file'}
</span> </span>
<span className='inline-flex items-center gap-2 rounded-full bg-[#f3fbf8] px-3 py-1 text-xs font-semibold text-[#257f73]'> <span className='inline-flex items-center gap-2 rounded-none bg-[#fffdf9] px-3 py-1 text-xs font-semibold text-[#35b7a5]'>
<BaseIcon path={mdiCloudUploadOutline} size={16} /> <BaseIcon path={mdiCloudUploadOutline} size={16} />
Upload Upload
</span> </span>
@ -362,7 +520,7 @@ const SessionMemory = () => {
</label> </label>
<button <button
type='button' type='button'
className='mt-3 inline-flex items-center gap-2 rounded-full bg-[#35b7a5] px-3 py-1.5 text-sm font-semibold text-white disabled:opacity-50' className='mt-3 inline-flex items-center gap-2 rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
disabled={isTranscribing || !audioFile} disabled={isTranscribing || !audioFile}
onClick={transcribeAudio} onClick={transcribeAudio}
> >
@ -377,7 +535,7 @@ const SessionMemory = () => {
<textarea <textarea
value={transcript} value={transcript}
onChange={(event) => setTranscript(event.target.value)} onChange={(event) => setTranscript(event.target.value)}
className='min-h-[220px] w-full rounded-lg border border-[#19192d]/10 bg-[#fffdf9] px-3 py-2 leading-6 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15' className='min-h-[220px] w-full rounded-none border border-[#19192d]/10 bg-[#fffdf9] px-4 py-3 leading-6 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15'
placeholder='Paste session transcript, coach notes, commitments, blockers, or a rough debrief...' placeholder='Paste session transcript, coach notes, commitments, blockers, or a rough debrief...'
/> />
<div className='mt-5'> <div className='mt-5'>
@ -392,9 +550,9 @@ const SessionMemory = () => {
<div className='space-y-4'> <div className='space-y-4'>
<Panel className='p-4'> <Panel className='p-4'>
<div className='flex items-start justify-between gap-4'> <div className='flex items-start justify-between gap-6'>
<div> <div>
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'> <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Coach review Coach review
</p> </p>
<h2 className='mt-2 text-lg font-semibold text-[#19192d]'> <h2 className='mt-2 text-lg font-semibold text-[#19192d]'>
@ -402,7 +560,7 @@ const SessionMemory = () => {
</h2> </h2>
</div> </div>
{hasDraft && ( {hasDraft && (
<span className='rounded-full bg-[#fbf8f1] px-3 py-1 text-xs font-semibold text-[#b17a1e]'> <span className='rounded-none bg-[#fffdf9] px-3 py-1 text-xs font-semibold text-[#35b7a5]'>
Draft not shared yet Draft not shared yet
</span> </span>
)} )}
@ -412,9 +570,9 @@ const SessionMemory = () => {
</div> </div>
{hasDraft ? ( {hasDraft ? (
<div className='mt-4 grid gap-4'> <div className='mt-4 grid gap-6'>
<label className='block'> <label className='block'>
<span className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'> <span className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Title Title
</span> </span>
<input <input
@ -422,7 +580,7 @@ const SessionMemory = () => {
onChange={(event) => onChange={(event) =>
updateDraft('title', event.target.value) updateDraft('title', event.target.value)
} }
className='mt-2 w-full rounded-lg border border-[#19192d]/10 bg-[#fffdf9] px-3 py-2 text-sm text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15' className='mt-2 w-full rounded-none border border-[#19192d]/10 bg-[#fffdf9] px-4 py-3 text-sm text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15'
/> />
</label> </label>
@ -453,7 +611,9 @@ const SessionMemory = () => {
<TextField <TextField
label='Follow-up email' label='Follow-up email'
value={draft.follow_up_email || ''} value={draft.follow_up_email || ''}
onChange={(value) => updateDraft('follow_up_email', value)} onChange={(value) =>
updateDraft('follow_up_email', value)
}
rows={4} rows={4}
/> />
<TextField <TextField
@ -474,7 +634,7 @@ const SessionMemory = () => {
<div className='flex flex-wrap gap-3'> <div className='flex flex-wrap gap-3'>
<button <button
type='button' type='button'
className='inline-flex items-center gap-2 rounded-full bg-[#19192d] px-3 py-1.5 text-sm font-semibold text-white disabled:opacity-50' className='inline-flex items-center gap-2 rounded-none bg-[#19192d] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
disabled={isSaving} disabled={isSaving}
onClick={() => saveMemory(false)} onClick={() => saveMemory(false)}
> >
@ -483,7 +643,7 @@ const SessionMemory = () => {
</button> </button>
<button <button
type='button' type='button'
className='inline-flex items-center gap-2 rounded-full bg-[#35b7a5] px-3 py-1.5 text-sm font-semibold text-white disabled:opacity-50' className='inline-flex items-center gap-2 rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50'
disabled={isSaving} disabled={isSaving}
onClick={() => saveMemory(true)} onClick={() => saveMemory(true)}
> >
@ -492,7 +652,7 @@ const SessionMemory = () => {
</button> </button>
<button <button
type='button' type='button'
className='inline-flex items-center gap-2 rounded-full border border-[#19192d]/10 bg-white px-3 py-1.5 text-sm font-semibold text-[#19192d]' className='inline-flex items-center gap-2 rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]'
onClick={copyFollowUp} onClick={copyFollowUp}
> >
<BaseIcon path={mdiContentCopy} size={18} /> <BaseIcon path={mdiContentCopy} size={18} />
@ -501,7 +661,7 @@ const SessionMemory = () => {
</div> </div>
</div> </div>
) : lastSavedSession ? ( ) : lastSavedSession ? (
<div className='mt-4 rounded-lg border border-[#35b7a5]/20 bg-[#f3fbf8] p-4'> <div className='mt-4 rounded-none border border-[#35b7a5]/20 bg-[#fffdf9] p-6'>
<BaseIcon <BaseIcon
path={ path={
lastSavedSession.status === 'shared' lastSavedSession.status === 'shared'
@ -509,7 +669,7 @@ const SessionMemory = () => {
: mdiCheckCircleOutline : mdiCheckCircleOutline
} }
size={22} size={22}
className='text-[#257f73]' className='text-[#35b7a5]'
/> />
<p className='mt-4 font-semibold text-[#19192d]'> <p className='mt-4 font-semibold text-[#19192d]'>
{lastSavedSession.status === 'shared' {lastSavedSession.status === 'shared'
@ -523,16 +683,16 @@ const SessionMemory = () => {
'the selected client'} 'the selected client'}
. .
</p> </p>
<p className='mt-3 text-sm font-semibold text-[#257f73]'> <p className='mt-3 text-sm font-semibold text-[#35b7a5]'>
You can find it in Recent memories below. You can find it in Recent memories below.
</p> </p>
</div> </div>
) : ( ) : (
<div className='mt-4 rounded-lg border border-dashed border-[#19192d]/10 bg-[#fffdf9] p-4'> <div className='mt-4 rounded-none border border-dashed border-[#19192d]/10 bg-[#fffdf9] p-6'>
<BaseIcon <BaseIcon
path={mdiLightbulbOnOutline} path={mdiLightbulbOnOutline}
size={22} size={22}
className='text-[#b17a1e]' className='text-[#35b7a5]'
/> />
<p className='mt-4 leading-6 text-[#72798a]'> <p className='mt-4 leading-6 text-[#72798a]'>
Generate memory from raw notes. The editable draft will Generate memory from raw notes. The editable draft will
@ -543,7 +703,7 @@ const SessionMemory = () => {
</Panel> </Panel>
<Panel> <Panel>
<div className='border-b border-[#19192d]/10 p-5'> <div className='border-b border-[#19192d]/10 p-7'>
<h2 className='text-lg font-semibold text-[#19192d]'> <h2 className='text-lg font-semibold text-[#19192d]'>
Recent memories Recent memories
</h2> </h2>
@ -551,7 +711,7 @@ const SessionMemory = () => {
<div className='divide-y divide-[#19192d]/10'> <div className='divide-y divide-[#19192d]/10'>
{sessions.map((session) => ( {sessions.map((session) => (
<div key={session.id} className='p-5'> <div key={session.id} className='p-5'>
<div className='flex items-start justify-between gap-4'> <div className='flex items-start justify-between gap-6'>
<div> <div>
<div className='flex flex-wrap items-center gap-2'> <div className='flex flex-wrap items-center gap-2'>
<p className='font-semibold text-[#19192d]'> <p className='font-semibold text-[#19192d]'>
@ -566,7 +726,7 @@ const SessionMemory = () => {
{session.status !== 'shared' && ( {session.status !== 'shared' && (
<button <button
type='button' type='button'
className='inline-flex items-center gap-2 rounded-full bg-[#35b7a5] px-3 py-1.5 text-sm font-semibold text-white' className='inline-flex items-center gap-2 rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white'
onClick={() => shareSession(session)} onClick={() => shareSession(session)}
> >
<BaseIcon path={mdiSendOutline} size={18} /> <BaseIcon path={mdiSendOutline} size={18} />

View File

@ -20,7 +20,7 @@ function Panel({
}) { }) {
return ( return (
<section <section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`} className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
> >
{children} {children}
</section> </section>
@ -40,8 +40,8 @@ function ActionButton({
}) { }) {
const className = const className =
variant === 'primary' variant === 'primary'
? 'rounded-full bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white' ? 'rounded-none bg-[#35b7a5] px-4 py-2 text-sm font-semibold text-white'
: 'rounded-full border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]'; : 'rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]';
if (href) { if (href) {
return ( return (
@ -128,8 +128,8 @@ const UsersTablesPage = () => {
</Head> </Head>
<main className='mx-auto max-w-7xl px-6 py-6'> <main className='mx-auto max-w-7xl px-6 py-6'>
<div className='mb-4 rounded-lg bg-[#19192d] p-5 text-white'> <div className='mb-4 rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#b17a1e]'> <div className='flex items-center gap-3 text-[#35b7a5]'>
<span className='text-lg'></span> <span className='text-lg'></span>
<span className='text-xs font-semibold uppercase tracking-[0.22em]'> <span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Team access Team access
@ -141,7 +141,7 @@ const UsersTablesPage = () => {
</p> </p>
</div> </div>
<Panel className='mb-4 p-4'> <Panel className='mb-4 p-6'>
<div className='flex flex-wrap items-center gap-3'> <div className='flex flex-wrap items-center gap-3'>
{hasCreatePermission && ( {hasCreatePermission && (
<ActionButton href='/users/users-new'>Add user</ActionButton> <ActionButton href='/users/users-new'>Add user</ActionButton>