Refine coaching UI and add audio recording
This commit is contained in:
parent
058b824a5c
commit
be3bbea7aa
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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'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>
|
||||
|
||||
@ -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's voice, not a generic
|
||||
chatbot voice.
|
||||
Client-facing content carries the coach'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>
|
||||
|
||||
@ -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]'>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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'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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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} />
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user