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'>
<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
</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
</span>
<span className='block text-lg font-semibold'>
@ -184,15 +184,15 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
</Link>
<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)}
>
<BaseIcon path={mdiClose} size={18} />
</button>
</div>
<div className='mt-5 rounded-lg border border-[#19192d]/10 bg-white p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.2em] text-[#b17a1e]'>
<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-[#35b7a5]'>
Today
</p>
<p className='mt-2 text-sm leading-6 text-[#72798a]'>
@ -211,10 +211,10 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
<Link
key={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
? '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} />
@ -224,8 +224,8 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
})}
</nav>
<div className='absolute inset-x-4 bottom-5 rounded-lg border border-[#19192d]/10 bg-[#fbf8f1] p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'>
<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-[#35b7a5]'>
Signed in
</p>
<p className='mt-2 truncate text-sm font-semibold'>
@ -233,7 +233,7 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
</p>
<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={() => {
dispatch(logoutUser());
router.push('/login');
@ -255,17 +255,17 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
)}
<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'>
<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)}
>
<BaseIcon path={mdiMenu} size={18} />
</button>
<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
</p>
<p className='mt-1 text-sm text-[#72798a]'>
@ -276,7 +276,7 @@ export default function LayoutAuthenticated({ children, permission }: Props) {
</div>
<Link
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
</Link>

View File

@ -48,7 +48,7 @@ function Panel({
}) {
return (
<section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`}
className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
>
{children}
</section>
@ -180,9 +180,9 @@ const ClientPortal = () => {
const openItems = (portalClient?.action_items || []).filter((item) => {
return item.status !== 'done';
});
const finishedCount =
(portalClient?.action_items || []).filter((item) => item.status === 'done')
.length;
const finishedCount = (portalClient?.action_items || []).filter(
(item) => item.status === 'done',
).length;
const latestSession = portalClient?.sessions?.[0];
return (
@ -193,14 +193,14 @@ const ClientPortal = () => {
<SectionMain>
<div className='mx-auto max-w-7xl'>
{!isClientUser && (
<Panel className='mb-4 p-4'>
<label className='block text-xs font-semibold uppercase tracking-[0.22em] text-[#b17a1e]'>
<Panel className='mb-4 p-6'>
<label className='block text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
Preview as client
</label>
<select
value={clientId}
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) => (
<option key={client.id} value={client.id}>
@ -212,11 +212,11 @@ const ClientPortal = () => {
)}
{portalClient && (
<div className='grid gap-4'>
<div className='rounded-lg border border-[#19192d]/10 bg-[#fffdf9] p-5'>
<div className='grid gap-4 lg:grid-cols-[1fr_280px]'>
<div className='grid gap-6'>
<div className='rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-7'>
<div className='grid gap-6 lg:grid-cols-[1fr_280px]'>
<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
</p>
<h1 className='mt-2 text-2xl font-semibold text-[#19192d]'>
@ -229,7 +229,7 @@ const ClientPortal = () => {
</p>
</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]'>
<BaseIcon path={mdiCalendarClock} size={18} />
Next session
@ -244,7 +244,7 @@ const ClientPortal = () => {
</div>
</div>
<div className='grid gap-4 md:grid-cols-3'>
<div className='grid gap-6 md:grid-cols-3'>
<Panel className='p-4'>
<p className='text-sm font-semibold text-[#72798a]'>
Open commitments
@ -271,12 +271,12 @@ const ClientPortal = () => {
</Panel>
</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'>
<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'>
<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} />
</span>
<div>
@ -289,25 +289,24 @@ const ClientPortal = () => {
</div>
</div>
</div>
<div className='space-y-3 p-4'>
<div className='space-y-3 p-6'>
{(portalClient.action_items || []).map((item) => {
const isDone =
item.status === 'done';
const isDone = item.status === 'done';
return (
<button
key={item.id}
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
? 'border-[#35b7a5]/30 bg-[#f3fbf8]'
? 'border-[#35b7a5]/30 bg-[#fffdf9]'
: 'border-[#19192d]/10 bg-white hover:bg-[#fffdf9]'
}`}
disabled={updatingItemId === item.id}
onClick={() => toggleItem(item)}
>
<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
? 'border-[#35b7a5] bg-[#35b7a5] text-white'
: 'border-[#19192d]/10 bg-white text-[#72798a]'
@ -336,7 +335,7 @@ const ClientPortal = () => {
<Panel className='p-4'>
<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} />
</span>
<div>
@ -354,7 +353,7 @@ const ClientPortal = () => {
setReflection(event.target.value);
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?'
/>
<div className='mt-3 flex items-center justify-between gap-3'>
@ -365,7 +364,7 @@ const ClientPortal = () => {
</p>
<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()}
onClick={saveReflection}
>
@ -377,9 +376,9 @@ const ClientPortal = () => {
<div className='space-y-4'>
<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'>
<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={mdiMessageReplyTextOutline}
size={18}
@ -396,9 +395,9 @@ const ClientPortal = () => {
</div>
</div>
<div className='space-y-3 p-4'>
<div className='space-y-3 p-6'>
{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]'>
{latestSession.title}
</p>
@ -410,7 +409,7 @@ const ClientPortal = () => {
{(portalClient.sessions || []).slice(1).map((session) => (
<details
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]'>
{session.title}
@ -424,20 +423,20 @@ const ClientPortal = () => {
</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]'>
Resources
</h2>
</div>
<div className='space-y-3 p-4'>
<div className='space-y-3 p-6'>
{(portalClient.resources || []).map((resource) => (
<a
key={resource.id}
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'>
<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} />
</span>
<div>

View File

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

View File

@ -81,7 +81,7 @@ function ShellCard({
}) {
return (
<section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`}
className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
>
{children}
</section>
@ -137,9 +137,9 @@ const Dashboard = () => {
</Head>
<SectionMain>
<div className='mx-auto max-w-7xl'>
<div className='grid gap-4 xl:grid-cols-[1.1fr_0.9fr]'>
<div className='rounded-lg bg-[#19192d] p-5 text-white'>
<div className='flex items-center gap-3 text-[#b17a1e]'>
<div className='grid gap-6 xl:grid-cols-[1.1fr_0.9fr]'>
<div className='rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#35b7a5]'>
<BaseIcon path={mdiViewDashboardOutline} size={18} />
<span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Workspace overview
@ -156,13 +156,13 @@ const Dashboard = () => {
<div className='mt-5 flex flex-wrap gap-3'>
<Link
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
</Link>
<Link
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
</Link>
@ -170,7 +170,7 @@ const Dashboard = () => {
</div>
<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
</p>
{nextPrepBrief ? (
@ -188,7 +188,7 @@ const Dashboard = () => {
</p>
<Link
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
<BaseIcon path={mdiArrowRight} size={18} />
@ -204,11 +204,11 @@ const Dashboard = () => {
</ShellCard>
</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) => (
<Link key={stat.label} href={stat.href}>
<ShellCard className='h-full p-5 transition'>
<div className='flex items-start justify-between gap-4'>
<ShellCard className='h-full p-7 transition'>
<div className='flex items-start justify-between gap-6'>
<div>
<p className='text-sm font-semibold text-[#72798a]'>
{stat.label}
@ -217,7 +217,7 @@ const Dashboard = () => {
{loading ? '...' : stat.value}
</p>
</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} />
</span>
</div>
@ -226,12 +226,12 @@ const Dashboard = () => {
))}
</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>
<div className='border-b border-[#19192d]/10 p-4'>
<div className='flex items-center justify-between gap-4'>
<div className='border-b border-[#19192d]/10 p-6'>
<div className='flex items-center justify-between gap-6'>
<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
</p>
<h2 className='mt-2 text-lg font-semibold'>
@ -251,9 +251,9 @@ const Dashboard = () => {
<Link
key={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>
<p className='font-semibold text-[#19192d]'>
{client.name}
@ -262,7 +262,7 @@ const Dashboard = () => {
{client.role_title} · {client.company}
</p>
</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'}
</span>
</div>
@ -272,10 +272,10 @@ const Dashboard = () => {
</ShellCard>
<ShellCard>
<div className='border-b border-[#19192d]/10 p-4'>
<div className='flex items-center justify-between gap-4'>
<div className='border-b border-[#19192d]/10 p-6'>
<div className='flex items-center justify-between gap-6'>
<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
</p>
<h2 className='mt-2 text-lg font-semibold'>
@ -309,10 +309,10 @@ const Dashboard = () => {
</div>
<ShellCard className='mt-4'>
<div className='border-b border-[#19192d]/10 p-4'>
<div className='flex items-center justify-between gap-4'>
<div className='border-b border-[#19192d]/10 p-6'>
<div className='flex items-center justify-between gap-6'>
<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
</p>
<h2 className='mt-2 text-lg font-semibold'>
@ -332,9 +332,9 @@ const Dashboard = () => {
<Link
key={brief.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>
<p className='font-semibold text-[#19192d]'>
{brief.client?.name}
@ -343,7 +343,7 @@ const Dashboard = () => {
{brief.client?.role_title} · {brief.client?.company}
</p>
</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
</span>
</div>

View File

@ -7,25 +7,22 @@ import { getPageTitle } from '../config';
const ui = {
page: 'bg-[#fffdf9] text-[#19192d]',
banner:
'bg-gradient-to-r from-[#35b7a5] via-[#95b76e] to-[#c38a25] text-white',
navShell:
'rounded-full bg-white shadow-[0_18px_60px_rgba(31,31,50,0.08)] ring-1 ring-[#19192d]/5',
banner: 'bg-[#19192d] text-white',
navShell: 'rounded-none bg-white ring-1 ring-[#19192d]/5',
ink: 'text-[#19192d]',
muted: 'text-[#72798a]',
accent: 'text-[#35b7a5]',
gold: 'text-[#b17a1e]',
gold: 'text-[#35b7a5]',
border: 'border-[#19192d]/10',
surface: 'bg-white',
softSurface: 'bg-[#fbf8f1]',
softSurface: 'bg-[#fffdf9]',
darkPanel: 'bg-[#19192d] text-white',
darkMuted: 'text-white/70',
button:
'bg-gradient-to-r from-[#36b39f] to-[#b98624] text-white shadow-[0_18px_45px_rgba(54,179,159,0.24)] transition hover:brightness-105',
button: 'bg-[#35b7a5] text-white transition hover:brightness-105',
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)]',
softCard: 'rounded-[1.75rem] border border-[#19192d]/10 bg-[#fbf8f1]',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#b17a1e]',
card: 'rounded-none border border-[#19192d]/10 bg-white ',
softCard: 'rounded-none border border-[#19192d]/10 bg-[#fffdf9]',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#35b7a5]',
heading: 'font-serif font-semibold tracking-tight text-[#19192d]',
};
@ -134,7 +131,7 @@ function Nav() {
href='/'
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
</span>
<span className='sr-only'>Coaching SaaS Workspace</span>
@ -150,7 +147,7 @@ function Nav() {
</nav>
<Link
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
</Link>
@ -194,7 +191,7 @@ function Mockup({ type }: { type: string }) {
<div className={`${ui.card} p-5`}>
<div className='flex items-center justify-between border-b border-[#19192d]/10 pb-4'>
<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
</span>
</div>
@ -213,9 +210,9 @@ function Mockup({ type }: { type: string }) {
].map((item) => (
<div
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 className='font-medium'>{item}</span>
@ -233,8 +230,8 @@ function Mockup({ type }: { type: string }) {
<h3 className='mt-2 text-2xl font-semibold'>
Sarah Mitchell · Session 4
</h3>
<div className='mt-5 rounded-2xl bg-[#fbf8f1] p-4'>
<p className='text-sm font-semibold text-[#b17a1e]'>Summary</p>
<div className='mt-5 rounded-none bg-[#fffdf9] p-4'>
<p className='text-sm font-semibold text-[#35b7a5]'>Summary</p>
<p className='mt-2 leading-7'>
Explored over-preparing for presentations and the shift from proving
competence to trusting it.
@ -244,7 +241,7 @@ function Mockup({ type }: { type: string }) {
{['Confidence', 'Delegation', 'Breakthrough'].map((item) => (
<span
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}
</span>
@ -252,11 +249,11 @@ function Mockup({ type }: { type: string }) {
</div>
<div className='mt-5 flex gap-3'>
<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
</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
</button>
</div>
@ -272,22 +269,22 @@ function Mockup({ type }: { type: string }) {
<span className={ui.muted}>Day 3</span>
</div>
<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='mt-2 leading-7'>
Last session you mentioned confidence feels different in small
groups vs large meetings. What did you notice this week?
</p>
</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='mt-2 leading-7'>
I led the Monday standup and it felt easier. I think naming it
helped.
</p>
</div>
<div className='rounded-2xl bg-[#e8f6f2] p-4'>
<p className='text-sm font-semibold text-[#248b7e]'>
<div className='rounded-none bg-[#fffdf9] p-4'>
<p className='text-sm font-semibold text-[#35b7a5]'>
Coach-approved suggestion
</p>
<p className='mt-2 leading-7'>
@ -305,20 +302,20 @@ function Mockup({ type }: { type: string }) {
<p className={`${ui.overline} text-xs`}>Prep brief</p>
<h3 className='mt-2 text-2xl font-semibold'>Session 5</h3>
<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={`mt-2 ${ui.muted}`}>
Confidence · Delegation · Board presence
</p>
</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={`mt-2 ${ui.muted}`}>
Lead Monday standup without notes. Delegate Q2 report.
</p>
</div>
<div className={`${ui.darkPanel} rounded-2xl p-4`}>
<p className='text-sm font-semibold text-[#c79a38]'>
<div className={`${ui.darkPanel} rounded-none p-4`}>
<p className='text-sm font-semibold text-[#35b7a5]'>
Suggested opening
</p>
<p className='mt-2 leading-7'>
@ -332,8 +329,8 @@ function Mockup({ type }: { type: string }) {
return (
<div className={`${ui.card} p-5`}>
<div className={`${ui.darkPanel} rounded-[1.5rem] p-5`}>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#c79a38]'>
<div className={`${ui.darkPanel} rounded-none p-5`}>
<p className='text-sm font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Your coaching space
</p>
<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) => (
<div
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={ui.accent}></span>
@ -371,7 +368,7 @@ function StepSection({
{step.title}
</h2>
<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}
</p>
</div>
@ -441,13 +438,13 @@ export default function HowItWorks() {
<div className='mt-9 flex flex-wrap justify-center gap-4'>
<Link
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
</Link>
<a
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
</a>
@ -485,7 +482,7 @@ export default function HowItWorks() {
<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>
<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
</p>
<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]) => (
<div
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>
<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={`${ui.card} overflow-hidden`}>
<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
</p>
<h3 className='mt-2 text-2xl font-semibold'>
@ -529,20 +526,20 @@ export default function HowItWorks() {
</p>
</div>
<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={`mt-2 leading-7 ${ui.muted}`}>
What is one boundary you could set this week to protect
strategic thinking time?
</p>
</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={`mt-2 ${ui.muted}`}>
Board presence, CPO conversations, delegation trust.
</p>
</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={`mt-2 ${ui.muted}`}>2 open · 5 done</p>
</div>
@ -604,10 +601,10 @@ export default function HowItWorks() {
<section id='pricing' className='px-5 py-20'>
<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'>
<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
</p>
<h2 className='mt-4 font-serif text-5xl font-semibold leading-tight'>
@ -625,7 +622,7 @@ export default function HowItWorks() {
</p>
<Link
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
</Link>
@ -655,7 +652,7 @@ export default function HowItWorks() {
</section>
<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?
</p>
<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'>
<Link
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
</Link>

View File

@ -7,25 +7,22 @@ import { getPageTitle } from '../config';
const ui = {
page: 'bg-[#fffdf9] text-[#19192d]',
banner:
'bg-gradient-to-r from-[#35b7a5] via-[#95b76e] to-[#c38a25] text-white',
navShell:
'rounded-full bg-white shadow-[0_18px_60px_rgba(31,31,50,0.08)] ring-1 ring-[#19192d]/5',
banner: 'bg-[#19192d] text-white',
navShell: 'rounded-none bg-white ring-1 ring-[#19192d]/5',
ink: 'text-[#19192d]',
muted: 'text-[#72798a]',
accent: 'text-[#35b7a5]',
gold: 'text-[#b17a1e]',
gold: 'text-[#35b7a5]',
border: 'border-[#19192d]/10',
surface: 'bg-white',
softSurface: 'bg-[#fbf8f1]',
softSurface: 'bg-[#fffdf9]',
darkPanel: 'bg-[#19192d] text-white',
darkMuted: 'text-white/70',
button:
'bg-gradient-to-r from-[#36b39f] to-[#b98624] text-white shadow-[0_18px_45px_rgba(54,179,159,0.24)] transition hover:brightness-105',
button: 'bg-[#35b7a5] text-white transition hover:brightness-105',
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)]',
softCard: 'rounded-[1.75rem] border border-[#19192d]/10 bg-[#fbf8f1]',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#b17a1e]',
card: 'rounded-none border border-[#19192d]/10 bg-white ',
softCard: 'rounded-none border border-[#19192d]/10 bg-[#fffdf9]',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#35b7a5]',
heading: 'font-serif font-semibold tracking-tight text-[#19192d]',
};
@ -162,7 +159,7 @@ export default function Starter() {
href='/'
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
</span>
<span className='sr-only'>Coaching SaaS Workspace</span>
@ -180,7 +177,7 @@ export default function Starter() {
</nav>
<Link
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
</Link>
@ -208,7 +205,7 @@ export default function Starter() {
<div className='mt-9 flex justify-center'>
<Link
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
</Link>
@ -229,21 +226,20 @@ export default function Starter() {
</div>
<div className='relative mx-auto mt-12 max-w-4xl'>
<div className='absolute -inset-12 rounded-full bg-[#35b7a5]/10 blur-3xl' />
<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>
<p className='text-xs uppercase tracking-[0.16em] text-[#c79a38]'>
<p className='text-xs uppercase tracking-[0.16em] text-[#35b7a5]'>
Session insights
</p>
<h2 className='mt-1 text-2xl font-semibold'>
Maya Chen · Session 4
</h2>
</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
</span>
</div>
@ -254,13 +250,13 @@ export default function Starter() {
'Decision rights',
'Founder visibility',
].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>
</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
className={`text-sm font-semibold uppercase tracking-[0.14em] ${ui.gold}`}
>
@ -277,8 +273,8 @@ export default function Starter() {
</div>
<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'>
<p className='text-sm font-semibold text-[#c79a38]'>
<div className='rounded-none bg-white/10 p-5'>
<p className='text-sm font-semibold text-[#35b7a5]'>
Pattern
</p>
<p className={`mt-2 leading-7 ${ui.darkMuted}`}>
@ -286,8 +282,8 @@ export default function Starter() {
explicit decision boundaries.
</p>
</div>
<div className='rounded-2xl bg-white/10 p-5'>
<p className='text-sm font-semibold text-[#c79a38]'>
<div className='rounded-none bg-white/10 p-5'>
<p className='text-sm font-semibold text-[#35b7a5]'>
Follow-up draft
</p>
<p className={`mt-2 leading-7 ${ui.darkMuted}`}>
@ -311,7 +307,7 @@ export default function Starter() {
the narrative instead of defending the roadmap.
</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
way?
@ -350,7 +346,7 @@ export default function Starter() {
key={title}
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}
</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='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
</p>
<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) => (
<div
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>
</div>
@ -400,7 +396,7 @@ export default function Starter() {
</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
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
</h3>
</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
</span>
</div>
@ -428,7 +424,7 @@ export default function Starter() {
].map(([value, label]) => (
<div
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={`mt-1 text-sm ${ui.muted}`}>{label}</p>
@ -436,7 +432,7 @@ export default function Starter() {
))}
</div>
<div className={`mt-5 rounded-2xl border p-5 ${ui.border}`}>
<div className={`mt-5 rounded-none border p-5 ${ui.border}`}>
<p
className={`text-sm font-semibold uppercase tracking-[0.14em] ${ui.gold}`}
>
@ -452,8 +448,8 @@ export default function Starter() {
</p>
</div>
<div className={`mt-5 rounded-2xl p-5 ${ui.darkPanel}`}>
<p className='text-sm font-semibold text-[#c79a38]'>
<div className={`mt-5 rounded-none p-5 ${ui.darkPanel}`}>
<p className='text-sm font-semibold text-[#35b7a5]'>
Suggested opening
</p>
<p className='mt-3 text-xl leading-8'>
@ -478,8 +474,8 @@ export default function Starter() {
</h2>
<p className={`mt-6 text-lg leading-8 ${ui.muted}`}>
Private notes stay private. Shared notes are approved.
Client-facing content carries the coach&apos;s voice, not a generic
chatbot voice.
Client-facing content carries the coach&apos;s voice, not a
generic chatbot voice.
</p>
</div>
<div className='grid grid-cols-1 gap-4 md:grid-cols-2'>
@ -504,7 +500,7 @@ export default function Starter() {
</div>
<Link
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
</Link>
@ -527,10 +523,10 @@ export default function Starter() {
<section id='pricing' className='px-5 py-20'>
<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'>
<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
</p>
<h2 className='mt-4 font-serif text-5xl font-semibold leading-tight'>
@ -552,7 +548,7 @@ export default function Starter() {
].map((item) => (
<div
key={item}
className={`rounded-2xl p-4 font-medium ${ui.softSurface}`}
className={`rounded-none p-4 font-medium ${ui.softSurface}`}
>
{item}
</div>
@ -560,7 +556,7 @@ export default function Starter() {
</div>
<Link
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
</Link>

View File

@ -36,7 +36,7 @@ function Panel({
}) {
return (
<section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`}
className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
>
{children}
</section>
@ -65,9 +65,12 @@ export default function IntakeLeads() {
async function archiveLead(leadId: string) {
setUpdatingLeadId(leadId);
const response = await axios.patch(`/coaching/intake-leads/${leadId}/status`, {
status: 'archived',
});
const response = await axios.patch(
`/coaching/intake-leads/${leadId}/status`,
{
status: 'archived',
},
);
setLeads((current) =>
current.map((lead) => {
if (lead.id === leadId) {
@ -87,8 +90,8 @@ export default function IntakeLeads() {
</Head>
<SectionMain>
<div className='mx-auto max-w-7xl'>
<div className='mb-4 rounded-lg bg-[#19192d] p-5 text-white'>
<div className='flex items-center gap-3 text-[#b17a1e]'>
<div className='mb-4 rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#35b7a5]'>
<BaseIcon path={mdiFormTextbox} size={18} />
<span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Intake
@ -101,16 +104,16 @@ export default function IntakeLeads() {
</p>
</div>
<div className='grid gap-4'>
<div className='grid gap-6'>
{leads.map((lead) => (
<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 className='flex flex-wrap items-center gap-3'>
<h2 className='text-lg font-semibold text-[#19192d]'>
{lead.name}
</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}
</span>
</div>
@ -133,7 +136,7 @@ export default function IntakeLeads() {
type='button'
disabled={updatingLeadId === 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} />
Convert to client
@ -144,7 +147,7 @@ export default function IntakeLeads() {
type='button'
disabled={updatingLeadId === 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} />
Archive
@ -153,25 +156,25 @@ export default function IntakeLeads() {
</div>
</div>
<div className='mt-5 grid gap-4 lg:grid-cols-3'>
<div className='rounded-lg bg-[#fffdf9] p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'>
<div className='mt-5 grid gap-6 lg:grid-cols-3'>
<div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Goal
</p>
<p className='mt-3 text-sm leading-6 text-[#72798a]'>
{lead.goal || 'No goal provided.'}
</p>
</div>
<div className='rounded-lg bg-[#fffdf9] p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'>
<div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Challenge
</p>
<p className='mt-3 text-sm leading-6 text-[#72798a]'>
{lead.challenge || 'No challenge provided.'}
</p>
</div>
<div className='rounded-lg bg-[#fffdf9] p-4'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#b17a1e]'>
<div className='rounded-none bg-[#fffdf9] p-6'>
<p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
Desired outcome
</p>
<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';
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 = {
name: string;
@ -83,7 +83,7 @@ export default function Intake() {
</Link>
<Link
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
</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]'>
<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
</p>
<h1 className='mt-4 font-serif text-5xl font-semibold leading-tight md:text-6xl'>
Start with the coaching context that matters.
</h1>
<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,
create a client record, and prepare the first session around your
goals.
Share what you want to work on. Your coach can review this, create
a client record, and prepare the first session around your goals.
</p>
</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 ? (
<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]'>
Received
</p>
@ -120,7 +119,7 @@ export default function Intake() {
</div>
) : (
<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'>
<input
required
@ -144,7 +143,7 @@ export default function Intake() {
</FieldLabel>
</div>
<div className='grid gap-4 md:grid-cols-2'>
<div className='grid gap-6 md:grid-cols-2'>
<FieldLabel label='Company'>
<input
value={values.company}
@ -170,7 +169,9 @@ export default function Intake() {
required
rows={4}
value={values.goal}
onChange={(event) => updateValue('goal', event.target.value)}
onChange={(event) =>
updateValue('goal', event.target.value)
}
className={fieldClass}
/>
</FieldLabel>
@ -197,7 +198,7 @@ export default function Intake() {
/>
</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
type='checkbox'
checked={values.consent_ai_notes}
@ -213,7 +214,7 @@ export default function Intake() {
<button
type='submit'
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'}
</button>

View File

@ -14,22 +14,19 @@ import { useAppDispatch, useAppSelector } from '../stores/hooks';
const ui = {
page: 'bg-[#fffdf9] text-[#19192d]',
banner:
'bg-gradient-to-r from-[#35b7a5] via-[#95b76e] to-[#c38a25] text-white',
navShell:
'rounded-full bg-white shadow-[0_18px_60px_rgba(31,31,50,0.08)] ring-1 ring-[#19192d]/5',
banner: 'bg-[#19192d] text-white',
navShell: 'rounded-none bg-white ring-1 ring-[#19192d]/5',
ink: 'text-[#19192d]',
muted: 'text-[#72798a]',
accent: 'text-[#35b7a5]',
gold: 'text-[#b17a1e]',
gold: 'text-[#35b7a5]',
border: 'border-[#19192d]/10',
surface: 'bg-white',
softSurface: 'bg-[#fbf8f1]',
softSurface: 'bg-[#fffdf9]',
darkPanel: 'bg-[#19192d] text-white',
button:
'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-[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-[#b17a1e]',
button: 'bg-[#35b7a5] text-white transition hover:brightness-105',
card: 'rounded-none border border-[#19192d]/10 bg-white ',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#35b7a5]',
heading: 'font-serif font-semibold tracking-tight text-[#19192d]',
};
@ -70,7 +67,7 @@ function Nav() {
href='/'
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
</span>
<span className='sr-only'>Coaching SaaS Workspace</span>
@ -85,7 +82,7 @@ function Nav() {
</nav>
<Link
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
</Link>
@ -218,7 +215,7 @@ export default function Login() {
<button
key={account.email}
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={() =>
setValues({
email: account.email,
@ -245,7 +242,7 @@ export default function Login() {
<Field
name='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>
@ -257,7 +254,7 @@ export default function Login() {
<Field
name='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
type='button'
@ -286,7 +283,7 @@ export default function Login() {
</label>
<Link
href='/forgot'
className='font-semibold text-[#248b7e] hover:underline'
className='font-semibold text-[#35b7a5] hover:underline'
>
Forgot password?
</Link>
@ -295,7 +292,7 @@ export default function Login() {
<button
type='submit'
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'}
</button>
@ -307,7 +304,7 @@ export default function Login() {
Don&apos;t have an account yet?{' '}
<Link
href='/register'
className='font-semibold text-[#248b7e] hover:underline'
className='font-semibold text-[#35b7a5] hover:underline'
>
Create one
</Link>

View File

@ -45,7 +45,7 @@ function Panel({
}) {
return (
<section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`}
className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
>
{children}
</section>
@ -70,7 +70,7 @@ function FieldWrap({
}
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 { currentUser } = useAppSelector((state) => state.auth);
@ -106,8 +106,8 @@ const EditUsers = () => {
</Head>
<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='flex items-center gap-3 text-[#b17a1e]'>
<div className='mb-4 rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#35b7a5]'>
<span className='text-lg'></span>
<span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Account
@ -129,7 +129,7 @@ const EditUsers = () => {
<div className='grid gap-5 xl:grid-cols-[180px_1fr]'>
<div>
<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 ? (
<Image
className='h-full w-full object-cover object-center'
@ -164,7 +164,7 @@ const EditUsers = () => {
</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'>
<Field
className={inputClassName}
@ -232,20 +232,20 @@ const EditUsers = () => {
<div className='flex flex-wrap justify-end gap-3 border-t border-[#19192d]/10 pt-5'>
<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')}
>
Cancel
</button>
<button
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
</button>
<button
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
</button>

View File

@ -11,18 +11,15 @@ import { getPageTitle } from '../config';
const ui = {
page: 'bg-[#fffdf9] text-[#19192d]',
banner:
'bg-gradient-to-r from-[#35b7a5] via-[#95b76e] to-[#c38a25] text-white',
navShell:
'rounded-full bg-white shadow-[0_18px_60px_rgba(31,31,50,0.08)] ring-1 ring-[#19192d]/5',
banner: 'bg-[#19192d] text-white',
navShell: 'rounded-none bg-white ring-1 ring-[#19192d]/5',
ink: 'text-[#19192d]',
muted: 'text-[#72798a]',
accent: 'text-[#35b7a5]',
border: 'border-[#19192d]/10',
button:
'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-[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-[#b17a1e]',
button: 'bg-[#35b7a5] text-white transition hover:brightness-105',
card: 'rounded-none border border-[#19192d]/10 bg-white ',
overline: 'text-sm font-bold uppercase tracking-[0.28em] text-[#35b7a5]',
heading: 'font-serif font-semibold tracking-tight text-[#19192d]',
};
@ -42,7 +39,7 @@ function Nav() {
href='/'
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
</span>
<span className='sr-only'>Coaching SaaS Workspace</span>
@ -57,7 +54,7 @@ function Nav() {
</nav>
<Link
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
</Link>
@ -188,7 +185,7 @@ export default function Register() {
<Field
type='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>
@ -199,7 +196,7 @@ export default function Register() {
<Field
type='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>
@ -210,14 +207,14 @@ export default function Register() {
<Field
type='password'
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>
<button
type='submit'
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'}
</button>
@ -228,7 +225,7 @@ export default function Register() {
Already have an account?{' '}
<Link
href='/login'
className='font-semibold text-[#248b7e] hover:underline'
className='font-semibold text-[#35b7a5] hover:underline'
>
Login
</Link>

View File

@ -5,6 +5,7 @@ import {
mdiFileDocumentEditOutline,
mdiLightbulbOnOutline,
mdiMicrophoneOutline,
mdiStopCircleOutline,
mdiSendOutline,
} from '@mdi/js';
import axios from 'axios';
@ -53,7 +54,7 @@ function Panel({
}) {
return (
<section
className={`rounded-lg border border-[#19192d]/10 bg-white ${className}`}
className={`rounded-none border border-[#19192d]/10 bg-white ${className}`}
>
{children}
</section>
@ -73,14 +74,14 @@ function TextField({
}) {
return (
<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}
</span>
<textarea
value={value}
rows={rows}
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>
);
@ -91,10 +92,8 @@ function StatusPill({ status }: { status?: string }) {
return (
<span
className={`rounded-full px-3 py-1 text-xs font-semibold ${
isShared
? 'bg-[#f3fbf8] text-[#35b7a5]'
: 'bg-[#fbf8f1] text-[#b17a1e]'
className={`rounded-none px-3 py-1 text-xs font-semibold ${
isShared ? 'bg-[#fffdf9] text-[#35b7a5]' : 'bg-[#fffdf9] text-[#35b7a5]'
}`}
>
{isShared ? 'Shared' : 'Coach draft'}
@ -147,13 +146,17 @@ const SessionMemory = () => {
const [transcript, setTranscript] = React.useState('');
const [draft, setDraft] = React.useState<MemoryDraft>(emptyDraft);
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 [isTranscribing, setIsTranscribing] = React.useState(false);
const [isSaving, setIsSaving] = React.useState(false);
const [notice, setNotice] = React.useState('');
const [lastSavedSession, setLastSavedSession] = React.useState<Session | null>(
null,
);
const [lastSavedSession, setLastSavedSession] =
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() {
const [clientsResponse, sessionsResponse] = await Promise.all([
@ -172,6 +175,26 @@ const SessionMemory = () => {
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) {
setDraft((current) => {
return {
@ -223,7 +246,9 @@ const SessionMemory = () => {
},
);
setTranscript(response.data.text || '');
setNotice('Audio transcribed. Review the transcript before generating memory.');
setNotice(
'Audio transcribed. Review the transcript before generating memory.',
);
} catch (error) {
setNotice(requestErrorMessage(error, 'Audio transcription failed.'));
} 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) {
setIsSaving(true);
const response = await axios.post('/coaching/session-memory/save', {
@ -253,9 +374,12 @@ const SessionMemory = () => {
}
async function shareSession(session: Session) {
const response = await axios.patch(`/coaching/sessions/${session.id}/share`, {
shared_client_notes: session.shared_client_notes,
});
const response = await axios.patch(
`/coaching/sessions/${session.id}/share`,
{
shared_client_notes: session.shared_client_notes,
},
);
setSessions((current) =>
current.map((currentSession) => {
@ -289,8 +413,8 @@ const SessionMemory = () => {
</Head>
<SectionMain>
<div className='mx-auto max-w-7xl'>
<div className='mb-4 rounded-lg bg-[#19192d] p-5 text-white'>
<div className='flex items-center gap-3 text-[#b17a1e]'>
<div className='mb-4 rounded-none bg-[#19192d] p-7 text-white'>
<div className='flex items-center gap-3 text-[#35b7a5]'>
<BaseIcon path={mdiFileDocumentEditOutline} size={18} />
<span className='text-xs font-semibold uppercase tracking-[0.22em]'>
Session Memory
@ -307,27 +431,27 @@ const SessionMemory = () => {
</div>
{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}
</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'>
<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
</p>
<h2 className='mt-2 text-lg font-semibold text-[#19192d]'>
Extract a session
</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
</label>
<select
value={clientId}
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) => (
<option key={client.id} value={client.id}>
@ -336,16 +460,50 @@ const SessionMemory = () => {
))}
</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]'>
<BaseIcon path={mdiMicrophoneOutline} size={18} />
Audio transcription
</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'>
{audioFile ? audioFile.name : 'Choose an audio file'}
</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} />
Upload
</span>
@ -362,7 +520,7 @@ const SessionMemory = () => {
</label>
<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}
onClick={transcribeAudio}
>
@ -377,7 +535,7 @@ const SessionMemory = () => {
<textarea
value={transcript}
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...'
/>
<div className='mt-5'>
@ -392,9 +550,9 @@ const SessionMemory = () => {
<div className='space-y-4'>
<Panel className='p-4'>
<div className='flex items-start justify-between gap-4'>
<div className='flex items-start justify-between gap-6'>
<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
</p>
<h2 className='mt-2 text-lg font-semibold text-[#19192d]'>
@ -402,7 +560,7 @@ const SessionMemory = () => {
</h2>
</div>
{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
</span>
)}
@ -412,9 +570,9 @@ const SessionMemory = () => {
</div>
{hasDraft ? (
<div className='mt-4 grid gap-4'>
<div className='mt-4 grid gap-6'>
<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
</span>
<input
@ -422,7 +580,7 @@ const SessionMemory = () => {
onChange={(event) =>
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>
@ -453,7 +611,9 @@ const SessionMemory = () => {
<TextField
label='Follow-up email'
value={draft.follow_up_email || ''}
onChange={(value) => updateDraft('follow_up_email', value)}
onChange={(value) =>
updateDraft('follow_up_email', value)
}
rows={4}
/>
<TextField
@ -474,7 +634,7 @@ const SessionMemory = () => {
<div className='flex flex-wrap gap-3'>
<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}
onClick={() => saveMemory(false)}
>
@ -483,7 +643,7 @@ const SessionMemory = () => {
</button>
<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}
onClick={() => saveMemory(true)}
>
@ -492,7 +652,7 @@ const SessionMemory = () => {
</button>
<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}
>
<BaseIcon path={mdiContentCopy} size={18} />
@ -501,7 +661,7 @@ const SessionMemory = () => {
</div>
</div>
) : 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
path={
lastSavedSession.status === 'shared'
@ -509,7 +669,7 @@ const SessionMemory = () => {
: mdiCheckCircleOutline
}
size={22}
className='text-[#257f73]'
className='text-[#35b7a5]'
/>
<p className='mt-4 font-semibold text-[#19192d]'>
{lastSavedSession.status === 'shared'
@ -523,16 +683,16 @@ const SessionMemory = () => {
'the selected client'}
.
</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.
</p>
</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
path={mdiLightbulbOnOutline}
size={22}
className='text-[#b17a1e]'
className='text-[#35b7a5]'
/>
<p className='mt-4 leading-6 text-[#72798a]'>
Generate memory from raw notes. The editable draft will
@ -543,7 +703,7 @@ const SessionMemory = () => {
</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]'>
Recent memories
</h2>
@ -551,7 +711,7 @@ const SessionMemory = () => {
<div className='divide-y divide-[#19192d]/10'>
{sessions.map((session) => (
<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 className='flex flex-wrap items-center gap-2'>
<p className='font-semibold text-[#19192d]'>
@ -566,7 +726,7 @@ const SessionMemory = () => {
{session.status !== 'shared' && (
<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)}
>
<BaseIcon path={mdiSendOutline} size={18} />

View File

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