Skip to content

Commit c707c84

Browse files
Added sidepanel (#15)
1 parent b0f10f5 commit c707c84

File tree

1 file changed

+53
-25
lines changed

1 file changed

+53
-25
lines changed

app/routes/clients.$id/route.tsx

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import Details from './details';
1717
import OnBehalfOf from './onBehalfOf';
1818
import { ActionIntent } from './actions';
1919

20+
import { useState } from 'react';
21+
2022
/**
2123
* Loads client data and related resources for the client details page. Requires authenticated user.
2224
* @param params - The route parameters, including the client ID.
@@ -139,65 +141,93 @@ export async function clientAction({ request, params }: ClientActionFunctionArgs
139141
return null;
140142
}
141143

144+
142145
/**
143146
* ClientPage component displays the details of a client, including its keys, scopes, and on-behalf-of configurations.
144147
*/
145148
export default function ClientPage() {
146149
const { t } = useTranslation();
147150
const data = useLoaderData<typeof clientLoader>();
148151

152+
const [aiPanelOpen, setAiPanelOpen] = useState(false);
153+
149154
if (isErrorResponse(data)) {
150155
return <AlertWrapper message={data.error} type="error"/>;
151156
}
152157

153158
const { client, JWK, onBehalfOf, scopesAccessibleForAll, scopesWithDelegationSource, scopesAvailableToOrganization } = data;
154159

160+
const openAiPanel = () => {
161+
setAiPanelOpen(true);
162+
};
163+
164+
const closeAiPanel = () => {
165+
setAiPanelOpen(false);
166+
};
167+
155168
return (
156-
<div>
169+
<div className="relative">
170+
<button
171+
onClick={openAiPanel}
172+
className="ds-button col-span-6 sm:col-span-4 xl:col-span-2 shadow my-2 py-3"
173+
data-variant="secondary"
174+
type="button"
175+
>
176+
Open Ai-Panel
177+
</button>
178+
179+
{/* 🧠 AI Sidepanel */}
180+
{aiPanelOpen && (
181+
<div className="fixed right-0 top-[64px] h-[calc(100%-64px)] w-full max-w-md bg-white shadow-lg border-l border-gray-300 z-50 overflow-y-auto">
182+
<div className="flex justify-between items-center p-4 border-b">
183+
<h2 className="text-lg font-semibold">AI Panel</h2>
184+
<button
185+
onClick={closeAiPanel}
186+
className="ds-button col-span-6 sm:col-span-4 xl:col-span-2 shadow my-2 py-3"
187+
data-variant="secondary"
188+
type="button"
189+
>
190+
X
191+
</button>
192+
</div>
193+
<div className="p-4">
194+
{/* Her kan du legge inn hva du vil */}
195+
<p>This is the AI panel for: <strong>{client.client_name}</strong></p>
196+
<p>Legg til AI-funksjonalitet her ✨</p>
197+
</div>
198+
</div>
199+
)}
200+
157201
<Tabs defaultValue="details">
158202
<Tabs.List className="top-0 z-10 bg-gray grid grid-cols-12 border-none">
159203
<div className='col-span-12'>
160204
<HeadingWrapper level={2} translate={false} heading={client.client_name || ''} className="py-4 bg-gray truncate block overflow-ellipsis"/>
161205
</div>
162206
<div className='col-span-12 flex'>
163-
<Tabs.Tab
164-
value="details"
165-
className="py-4 px-8 border-solid border-b">
207+
<Tabs.Tab value="details" className="py-4 px-8 border-solid border-b">
166208
{t('client_page.details')}
167209
</Tabs.Tab>
168-
<Tabs.Tab
169-
value="keys"
170-
className="py-4 px-8 border-solid border-b">
210+
<Tabs.Tab value="keys" className="py-4 px-8 border-solid border-b">
171211
{t('key', { count: 0 })}
172212
</Tabs.Tab>
173-
<Tabs.Tab
174-
value="scopes"
175-
className="py-4 px-8 border-solid border-b">
213+
<Tabs.Tab value="scopes" className="py-4 px-8 border-solid border-b">
176214
{t('scope', { count: 0 })}
177215
</Tabs.Tab>
178216
{(client.integration_type === IntegrationType.IDPORTEN || client.integration_type === IntegrationType.API_KLIENT || client.integration_type === IntegrationType.KRR) && (
179-
<Tabs.Tab
180-
value="onBehalfOf"
181-
className="py-4 px-8 border-solid border-b">
217+
<Tabs.Tab value="onBehalfOf" className="py-4 px-8 border-solid border-b">
182218
OnBehalfOf
183219
</Tabs.Tab>
184220
)}
185221
</div>
186222
</Tabs.List>
187223

188-
<Tabs.Panel
189-
value="details"
190-
className="p-0">
224+
<Tabs.Panel value="details" className="p-0">
191225
<Details client={client}/>
192226
</Tabs.Panel>
193-
<Tabs.Panel
194-
value="keys"
195-
className="p-0">
227+
<Tabs.Panel value="keys" className="p-0">
196228
<Keys jwks={JWK ?? []}/>
197229
</Tabs.Panel>
198-
<Tabs.Panel
199-
value="scopes"
200-
className="p-0">
230+
<Tabs.Panel value="scopes" className="p-0">
201231
<Scopes
202232
scopes={client.scopes ?? []}
203233
scopesAccessibleForAll={scopesAccessibleForAll}
@@ -206,9 +236,7 @@ export default function ClientPage() {
206236
clientIntegrationType={client.integration_type!}
207237
/>
208238
</Tabs.Panel>
209-
<Tabs.Panel
210-
value="onBehalfOf"
211-
className="p-0">
239+
<Tabs.Panel value="onBehalfOf" className="p-0">
212240
<OnBehalfOf onBehalfOfs={onBehalfOf!}/>
213241
</Tabs.Panel>
214242
</Tabs>

0 commit comments

Comments
 (0)