#28 Cycle Archive/Management Page#35
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: b-at-neu <144247685+b-at-neu@users.noreply.github.com>
| }; | ||
|
|
||
| interface CyclesManagerProps { | ||
| cycles: CycleWithCounts[]; |
There was a problem hiding this comment.
this can be in one interface together
There was a problem hiding this comment.
Done in 8116744. CycleWithCounts is now a single exported interface and CyclesManagerProps references it directly.
| export default function CyclesManager({ cycles }: CyclesManagerProps) { | ||
| const router = useRouter(); | ||
|
|
||
| // Create modal state |
There was a problem hiding this comment.
Done in 8116744. The create cycle modal now uses React Hook Form with a Zod schema (name: z.string().min(1, 'Cycle name is required')). Two handleSubmit wrappers are created via a shared handleCreate(setActive) factory to handle the "Create as Inactive" vs "Create & Set Active" split.
| </TableCell> | ||
| <TableCell className="text-right"> | ||
| <div className="flex justify-end gap-2"> | ||
| <Link href={`/cycles/${cycle.id}`}> |
There was a problem hiding this comment.
This should go to /admin/cycles/[id]
There was a problem hiding this comment.
Fixed in 8116744 — the View link now goes to /admin/cycles/${cycle.id}.
| @@ -0,0 +1,292 @@ | |||
| 'use client'; | |||
There was a problem hiding this comment.
lets split up this file into smaller components, also we can colocate this with the only page its on
There was a problem hiding this comment.
Done in 8116744. Removed components/CyclesManager.tsx and split into three colocated files in app/admin/cycles/: cycles-manager.tsx (table + state orchestration), create-cycle-modal.tsx (create form), and set-active-modal.tsx (confirmation modal).
| * Create a new cycle. If setActive is true, deactivate all other cycles. | ||
| */ | ||
| export async function createCycle(name: string, setActive: boolean) { | ||
| if (!name.trim()) { |
There was a problem hiding this comment.
this can be handled with zod validation on client side
There was a problem hiding this comment.
Removed in 8116744. Name validation is now handled entirely by the Zod schema in create-cycle-modal.tsx.
|
|
||
| return { success: true }; | ||
| } catch (error) { | ||
| console.error('Error setting active cycle:', error); |
There was a problem hiding this comment.
this isn't graceful, see how error handling works elsewhere
There was a problem hiding this comment.
Updated in 8116744 to return { success: false, error: 'Failed to set active cycle' } — static string matching the settings.ts pattern.
| return { success: true }; | ||
| } catch (error) { | ||
| console.error('Error deleting cycle:', error); | ||
| return { |
There was a problem hiding this comment.
handle errors more gracefully
There was a problem hiding this comment.
Updated in 8116744 to return { success: false, error: 'Failed to delete cycle' } — static string matching the settings.ts pattern.
…w link, clean up actions Co-authored-by: b-at-neu <144247685+b-at-neu@users.noreply.github.com>
| : `Cycle "${data.name}" created` | ||
| ); | ||
| onClose(); | ||
| router.refresh(); |
There was a problem hiding this comment.
we already revalidate the page
There was a problem hiding this comment.
Removed in ba91dc2 — router.refresh() and the useRouter import are gone from create-cycle-modal.tsx. The revalidatePath('/admin') in the server action is sufficient.
| onClose(); | ||
| router.refresh(); | ||
| } else { | ||
| setServerError(result.error || 'Failed to create cycle'); |
There was a problem hiding this comment.
why does this have to be a useState? Can't we use react hook form properly?
There was a problem hiding this comment.
Fixed in ba91dc2. Replaced useState(serverError) with RHF's setError('root', { message: result.error }). The error is now read from errors.root?.message instead.
| Set Active | ||
| </Button> | ||
| )} | ||
| {!cycle.isActive && isEmpty(cycle) && ( |
There was a problem hiding this comment.
lets deactivate this button on empty, not remove it
There was a problem hiding this comment.
Updated in ba91dc2 — the delete button is now always rendered for inactive cycles but has disabled={!isEmpty(cycle)} when the cycle has data.
| if (result.success) { | ||
| toast.success(`"${cycle.name}" is now the active cycle`); | ||
| onClose(); | ||
| router.refresh(); |
There was a problem hiding this comment.
Removed in ba91dc2. Switched to AlertDialog which handles its own open/close lifecycle, so no useState or useRouter is needed.
| }; | ||
|
|
||
| return ( | ||
| <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"> |
There was a problem hiding this comment.
don't do this, just use a dialog or alertdialog from shadcn
There was a problem hiding this comment.
Done in ba91dc2. Added @radix-ui/react-alert-dialog and the standard shadcn AlertDialog component (components/ui/alert-dialog.tsx), then rewrote set-active-modal.tsx to use AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogAction, and AlertDialogCancel.
| return { success: true, cycle }; | ||
| } catch (error) { | ||
| console.error('Error creating cycle:', error); | ||
| return { success: false, error: 'Failed to create cycle' }; |
There was a problem hiding this comment.
You don't need to console error. also just return { error: text }
There was a problem hiding this comment.
you don't need the sucess false, just make an errortype and have a helper to check for it,
There was a problem hiding this comment.
Done in ba91dc2. Removed all console.error calls. Introduced ActionError = { error: string } type, isActionError(result: unknown): result is ActionError helper, and changed all returns to { error: 'message' } on failure and { cycle } / {} on success. The success boolean is gone entirely.
…ePath cleanup, rhf setError Co-authored-by: b-at-neu <144247685+b-at-neu@users.noreply.github.com>
|
…ib/actions/utils.ts Co-authored-by: b-at-neu <144247685+b-at-neu@users.noreply.github.com>
Fixed in 74b218e. The root cause was that |
getCyclesWithCounts()tolib/data/cycles.tslib/actions/cycles.tswithcreateCycle,setActiveCycle,deleteCycleserver actionsapp/admin/cycles/app/admin/cycles/page.tsxadmin pageapp/admin/page.tsx)isActionError/ActionErrortolib/actions/utils.ts(non-server file) —'use server'files can only export async functionsOriginal prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.