129 lines
4.6 KiB
TypeScript
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
|