@@ -6,29 +6,16 @@ import { authClient } from '@/utils/auth-client';
66import { Alert , AlertDescription , AlertTitle } from '@comp/ui/alert' ;
77import { Button } from '@comp/ui/button' ;
88import { Card , CardContent , CardDescription , CardHeader , CardTitle } from '@comp/ui/card' ;
9- import {
10- DropdownMenu ,
11- DropdownMenuContent ,
12- DropdownMenuItem ,
13- DropdownMenuTrigger ,
14- } from '@comp/ui/dropdown-menu' ;
159import { Icons } from '@comp/ui/icons' ;
1610import type { Member , Policy , User } from '@db' ;
1711import { Control } from '@db' ;
1812import { format } from 'date-fns' ;
19- import {
20- ArchiveIcon ,
21- ArchiveRestoreIcon ,
22- MoreVertical ,
23- PencilIcon ,
24- ShieldCheck ,
25- ShieldX ,
26- Trash2 ,
27- } from 'lucide-react' ;
13+ import { ArchiveIcon , ArchiveRestoreIcon , ShieldCheck , ShieldX } from 'lucide-react' ;
2814import { useAction } from 'next-safe-action/hooks' ;
2915import { useQueryState } from 'nuqs' ;
3016import { useState } from 'react' ;
3117import { toast } from 'sonner' ;
18+ import { regeneratePolicyAction } from '../actions/regenerate-policy' ;
3219import { PolicyActionDialog } from './PolicyActionDialog' ;
3320import { PolicyArchiveSheet } from './PolicyArchiveSheet' ;
3421import { PolicyControlMappings } from './PolicyControlMappings' ;
@@ -79,10 +66,8 @@ export function PolicyOverview({
7966 // Dialog state for approval/denial actions
8067 const [ approveDialogOpen , setApproveDialogOpen ] = useState ( false ) ;
8168 const [ denyDialogOpen , setDenyDialogOpen ] = useState ( false ) ;
82- const [ deleteDialogOpen , setDeleteDialogOpen ] = useState ( false ) ;
83-
84- // Dropdown menu state
85- const [ dropdownOpen , setDropdownOpen ] = useState ( false ) ;
69+ const [ deleteOpenParam , setDeleteOpenParam ] = useQueryState ( 'delete-policy' ) ;
70+ const [ regenerateOpen , setRegenerateOpen ] = useState ( false ) ;
8671
8772 // Handle approve with optional comment
8873 const handleApprove = ( comment ?: string ) => {
@@ -149,22 +134,26 @@ export function PolicyOverview({
149134 </ Alert >
150135 ) }
151136 { policy ?. isArchived && (
152- < Alert >
153- < div className = "flex items-center gap-2" >
154- < ArchiveIcon className = "h-4 w-4" />
155- < div className = "font-medium" > { 'This policy is archived' } </ div >
137+ < Alert className = "flex items-start justify-between gap-3" >
138+ < div className = "flex items-start gap-2" >
139+ < ArchiveIcon className = "mt-0.5 h-4 w-4" />
140+ < div className = "space-y-1" >
141+ < div className = "font-medium" > This policy is archived</ div >
142+ < AlertDescription >
143+ Archived on { format ( new Date ( policy ?. updatedAt ?? new Date ( ) ) , 'PPP' ) }
144+ </ AlertDescription >
145+ </ div >
146+ </ div >
147+ < div className = "shrink-0" >
148+ < Button
149+ size = "sm"
150+ variant = "outline"
151+ onClick = { ( ) => setArchiveOpen ( 'true' ) }
152+ className = "gap-1"
153+ >
154+ < ArchiveRestoreIcon className = "h-3 w-3" /> Restore
155+ </ Button >
156156 </ div >
157- < AlertDescription >
158- { policy ?. isArchived && (
159- < >
160- { 'Archived on' } { format ( new Date ( policy ?. updatedAt ?? new Date ( ) ) , 'PPP' ) }
161- </ >
162- ) }
163- </ AlertDescription >
164- < Button size = "sm" variant = "outline" onClick = { ( ) => setArchiveOpen ( 'true' ) } >
165- < ArchiveRestoreIcon className = "h-3 w-3" />
166- { 'Restore' }
167- </ Button >
168157 </ Alert >
169158 ) }
170159
@@ -176,55 +165,8 @@ export function PolicyOverview({
176165 < Icons . Policies className = "h-4 w-4" />
177166 { policy ?. name }
178167 </ div >
179- < DropdownMenu open = { dropdownOpen } onOpenChange = { setDropdownOpen } >
180- < DropdownMenuTrigger asChild >
181- < Button
182- size = "icon"
183- variant = "ghost"
184- disabled = { isPendingApproval }
185- className = "m-0 size-auto p-2 hover:bg-transparent"
186- >
187- < MoreVertical className = "h-4 w-4" />
188- </ Button >
189- </ DropdownMenuTrigger >
190- < DropdownMenuContent align = "end" >
191- < DropdownMenuItem
192- onClick = { ( ) => {
193- setDropdownOpen ( false ) ;
194- setOpen ( 'true' ) ;
195- } }
196- disabled = { isPendingApproval }
197- >
198- < PencilIcon className = "mr-2 h-4 w-4" />
199- { 'Edit policy' }
200- </ DropdownMenuItem >
201- < DropdownMenuItem
202- onClick = { ( ) => {
203- setDropdownOpen ( false ) ;
204- setArchiveOpen ( 'true' ) ;
205- } }
206- disabled = { isPendingApproval }
207- >
208- { policy ?. isArchived ? (
209- < ArchiveRestoreIcon className = "mr-2 h-4 w-4" />
210- ) : (
211- < ArchiveIcon className = "mr-2 h-4 w-4" />
212- ) }
213- { policy ?. isArchived ? 'Restore policy' : 'Archive policy' }
214- </ DropdownMenuItem >
215- < DropdownMenuItem
216- onClick = { ( ) => {
217- setDropdownOpen ( false ) ;
218- setDeleteDialogOpen ( true ) ;
219- } }
220- disabled = { isPendingApproval }
221- className = "text-destructive focus:text-destructive"
222- >
223- < Trash2 className = "mr-2 h-4 w-4" />
224- Delete
225- </ DropdownMenuItem >
226- </ DropdownMenuContent >
227- </ DropdownMenu >
168+ { /* Redundant gear removed; actions moved to breadcrumb header */ }
169+ < div className = "h-6" />
228170 </ div >
229171 </ CardTitle >
230172 < CardDescription > { policy ?. description } </ CardDescription >
@@ -276,10 +218,24 @@ export function PolicyOverview({
276218
277219 { /* Delete Dialog */ }
278220 < PolicyDeleteDialog
279- isOpen = { deleteDialogOpen }
280- onClose = { ( ) => setDeleteDialogOpen ( false ) }
221+ isOpen = { Boolean ( deleteOpenParam ) }
222+ onClose = { ( ) => setDeleteOpenParam ( null ) }
281223 policy = { policy }
282224 />
225+ { /* Regenerate Dialog */ }
226+ < PolicyActionDialog
227+ isOpen = { regenerateOpen }
228+ onClose = { ( ) => setRegenerateOpen ( false ) }
229+ onConfirm = { async ( ) => {
230+ if ( ! policy ?. id ) return ;
231+ await regeneratePolicyAction ( { policyId : policy . id } ) ;
232+ toast . info ( 'Regeneration started' ) ;
233+ } }
234+ title = "Regenerate Policy"
235+ description = "This will regenerate the policy content and mark it for review. Continue?"
236+ confirmText = "Regenerate"
237+ confirmIcon = { < Icons . AI className = "h-4 w-4" /> }
238+ />
283239 </ >
284240 ) }
285241 </ div >
0 commit comments