import { mdiAccountCircle, mdiBookOpenVariant, mdiCheckCircleOutline, mdiChevronRight, mdiMessageReplyTextOutline, } from '@mdi/js'; import axios from 'axios'; import Head from 'next/head'; import React from 'react'; import type { ReactElement } from 'react'; import BaseIcon from '../components/BaseIcon'; import SectionMain from '../components/SectionMain'; import { getPageTitle } from '../config'; import LayoutAuthenticated from '../layouts/Authenticated'; type PortalClient = { id: string; name: string; goals?: string; sessions?: Array<{ id: string; title: string; shared_client_notes?: string }>; action_items?: Array<{ id: string; title: string; status: string }>; resources?: Array<{ id: string; title: string; description?: string; url?: string; }>; }; function Panel({ children, className = '', }: { children: React.ReactNode; className?: string; }) { return (
{children}
); } const ClientPortal = () => { const [clients, setClients] = React.useState< Array<{ id: string; name: string }> >([]); const [clientId, setClientId] = React.useState(''); const [portalClient, setPortalClient] = React.useState( null, ); React.useEffect(() => { async function loadClients() { const response = await axios.get('/coaching/clients'); setClients(response.data); if (response.data.length > 0) { setClientId(response.data[0].id); } } loadClients(); }, []); React.useEffect(() => { async function loadPortal() { if (!clientId) { return; } const response = await axios.get(`/coaching/client-portal/${clientId}`); setPortalClient(response.data); } loadPortal(); }, [clientId]); return ( <> {getPageTitle('Client Portal')}
Client portal

Client portal preview

Preview the client-facing workspace with shared notes, commitments, resources, and a pre-session reflection prompt.

MVP note: this is still a coach-visible preview. Final client access should be a client role or magic-link route.

{portalClient && (

Your coaching workspace

{portalClient.name}

{portalClient.goals}

Shared session notes

Only coach-approved notes appear here.

{(portalClient.sessions || []).map((session) => (

{session.title}

{session.shared_client_notes}

))}

Commitments

{(portalClient.action_items || []).map((item) => (

{item.title}

{item.status.replace('_', ' ')}

))}

Resources

{(portalClient.resources || []).map((resource) => (

{resource.title}

{resource.description}

))}

Pre-session reflection

What changed since last time?

Final MVP should let the client answer this before a session, then feed the response into the coach prep brief.

)}
); }; ClientPortal.getLayout = function getLayout(page: ReactElement) { return {page}; }; export default ClientPortal;