@@ -17,6 +17,8 @@ import Details from './details';
1717import OnBehalfOf from './onBehalfOf' ;
1818import { 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 */
145148export 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