40234-vm/frontend/src/pages/client-portal.tsx
2026-06-09 11:15:03 +00:00

129 lines
4.6 KiB
TypeScript

import * as icon from '@mdi/js';
import Head from 'next/head'
import React from 'react'
import axios from 'axios';
import type { ReactElement } from 'react'
import LayoutAuthenticated from '../layouts/Authenticated'
import SectionMain from '../components/SectionMain'
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton'
import CardBox from '../components/CardBox'
import { getPageTitle } from '../config'
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 }>;
};
const ClientPortal = () => {
const [clients, setClients] = React.useState<Array<{ id: string; name: string }>>([]);
const [clientId, setClientId] = React.useState('');
const [portalClient, setPortalClient] = React.useState<PortalClient | null>(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 (
<>
<Head>
<title>{getPageTitle('Client Portal')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={icon.mdiAccountCircle} title="Client Portal Preview" main>
{''}
</SectionTitleLineWithButton>
<CardBox className="mb-6">
<label className="mb-2 block text-sm font-medium text-gray-600">Preview as client</label>
<select
value={clientId}
onChange={(event) => setClientId(event.target.value)}
className="w-full rounded border border-gray-300 px-3 py-2 md:w-96"
>
{clients.map((client) => (
<option key={client.id} value={client.id}>{client.name}</option>
))}
</select>
</CardBox>
{portalClient && (
<div className="grid grid-cols-1 gap-6 xl:grid-cols-[1.05fr_0.95fr]">
<CardBox>
<p className="text-sm font-medium uppercase tracking-wide text-emerald-700">Your coaching workspace</p>
<h2 className="mt-1 text-2xl font-semibold">{portalClient.name}</h2>
<p className="mt-4 leading-7 text-gray-600">{portalClient.goals}</p>
<h3 className="mt-6 mb-3 font-semibold">Shared session notes</h3>
<div className="space-y-3">
{(portalClient.sessions || []).map((session) => (
<div key={session.id} className="rounded border border-gray-200 p-4">
<p className="font-medium">{session.title}</p>
<p className="mt-2 leading-6 text-gray-600">{session.shared_client_notes}</p>
</div>
))}
</div>
</CardBox>
<div className="space-y-6">
<CardBox>
<h3 className="mb-3 font-semibold">Commitments</h3>
<div className="space-y-3">
{(portalClient.action_items || []).map((item) => (
<div key={item.id} className="rounded border border-gray-200 p-3">
<p className="font-medium">{item.title}</p>
<p className="mt-1 text-sm text-gray-500">{item.status.replace('_', ' ')}</p>
</div>
))}
</div>
</CardBox>
<CardBox>
<h3 className="mb-3 font-semibold">Resources</h3>
<div className="space-y-3">
{(portalClient.resources || []).map((resource) => (
<a key={resource.id} href={resource.url} className="block rounded border border-gray-200 p-3 hover:bg-gray-50">
<p className="font-medium">{resource.title}</p>
<p className="mt-1 text-sm leading-6 text-gray-500">{resource.description}</p>
</a>
))}
</div>
</CardBox>
</div>
</div>
)}
</SectionMain>
</>
)
}
ClientPortal.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated>{page}</LayoutAuthenticated>
}
export default ClientPortal