Skip to content

Instantly share code, notes, and snippets.

@chrishannah
Created March 30, 2026 03:59
Show Gist options
  • Select an option

  • Save chrishannah/8998b44799266cfc7873c3ec19867577 to your computer and use it in GitHub Desktop.

Select an option

Save chrishannah/8998b44799266cfc7873c3ec19867577 to your computer and use it in GitHub Desktop.
Entry Types Management UI - Implementation Plan for Miniship #40

Entry Types Management UI - Implementation Plan

Overview

Add a UI for users to view, edit, reorder, and delete entry types in their changelogs. This solves the issue where users can't manage duplicate or unwanted entry types after they're created.

Context

  • Import logic was creating duplicate entry types (e.g., 'Added' and 'added') due to case mismatches (now fixed)
  • Users need a way to clean up existing duplicates and manage custom types
  • Currently no UI to edit, delete, or reorder entry types after creation

Requirements

1. Entry Types Management Page

Route: /dashboard/[id]/settings/types

Access:

  • Accessible from changelog settings page
  • Link/button: "Manage Entry Types"

2. Entry Types List

Display:

  • Show all entry types (defaults + custom) in a list/grid
  • Each entry type card shows:
    • Icon/emoji
    • Name
    • Color indicator
    • Usage count (number of items using this type)
    • Badge: "Default" or "Custom"
    • Actions: Edit, Delete, Move Up/Down

Ordering:

  • Display types in current database order
  • Allow reordering via up/down arrows or drag-and-drop

3. Edit Entry Type

Modal/Form:

  • Edit name (text input)
  • Edit icon (emoji picker or text input)
  • Edit color (color picker or preset swatches)
  • Can't edit default types (grayed out/disabled)

Validation:

  • Name required, 1-50 chars
  • No duplicate names (case-insensitive check)

API: PATCH /api/changelogs/[id]/types/[typeId]

4. Delete Entry Type

Behavior:

  • Show usage count
  • If type is in use (has items):
    • Option A: Block deletion with error message
    • Option B: Allow deletion but require converting items to another type first
  • Can't delete default types
  • Show confirmation dialog

API: DELETE /api/changelogs/[id]/types/[typeId]

5. Reorder Entry Types

Options:

  • Option A: Up/Down buttons (simpler)
  • Option B: Drag-and-drop (better UX, more complex)

API: PATCH /api/changelogs/[id]/types/reorder

  • Body: { typeIds: [id1, id2, id3, ...] } (array in new order)

6. Security

  • Verify changelog ownership
  • Require authentication
  • Check user owns the changelog before allowing edits

Database Changes

Migration: Add order column

ALTER TABLE entry_types ADD COLUMN "order" INTEGER DEFAULT 0;

Backfill:

  • Update existing types to set order based on current ID or created date
  • Defaults (id where changelogId is null) get order 0-5
  • Custom types get sequential order starting from 100

Schema update

export const entryTypes = pgTable('entry_types', {
  // ... existing fields
  order: integer('order').notNull().default(0),
});

API Endpoints

1. PATCH /api/changelogs/[id]/types/[typeId]

Request:

{
  "name": "New Name",
  "icon": "🎉",
  "color": "#ff6b6b"
}

Response:

{
  "success": true,
  "type": { ... }
}

Errors:

  • 401: Not authenticated
  • 403: Not owner of changelog
  • 404: Type not found
  • 400: Can't edit default type
  • 400: Duplicate name

2. DELETE /api/changelogs/[id]/types/[typeId]

Response:

{
  "success": true
}

Errors:

  • 401: Not authenticated
  • 403: Not owner of changelog
  • 404: Type not found
  • 400: Can't delete default type
  • 400: Type is in use (if blocking deletion)

3. PATCH /api/changelogs/[id]/types/reorder

Request:

{
  "typeIds": ["uuid1", "uuid2", "uuid3"]
}

Response:

{
  "success": true
}

Errors:

  • 401: Not authenticated
  • 403: Not owner of changelog
  • 400: Invalid type IDs

UI Components

EntryTypesPage

Location: app/dashboard/[id]/settings/types/page.tsx

  • Server component
  • Verify auth and ownership
  • Fetch entry types with usage counts
  • Render EntryTypesManager client component

EntryTypesManager

Location: app/dashboard/[id]/settings/types/EntryTypesManager.tsx

  • Client component
  • Display entry types list
  • Handle edit/delete/reorder actions
  • Show modals/dialogs

EntryTypeCard

Location: app/dashboard/[id]/settings/types/EntryTypeCard.tsx

  • Display single entry type
  • Show icon, name, color, badge
  • Usage count
  • Action buttons

EditEntryTypeModal

Location: app/dashboard/[id]/settings/types/EditEntryTypeModal.tsx

  • Edit form
  • Color picker
  • Icon picker
  • Validation

DeleteConfirmDialog

Location: app/dashboard/[id]/settings/types/DeleteConfirmDialog.tsx

  • Confirmation dialog
  • Show usage warning
  • Confirm/cancel buttons

Implementation Steps

Phase 1: Database & API (Core)

  1. Add order column migration
  2. Backfill order values for existing types
  3. Create PATCH endpoint for updating types
  4. Create DELETE endpoint (with validation)
  5. Create PATCH endpoint for reordering

Phase 2: UI (Core Features)

  1. Create entry types management page route
  2. Build EntryTypesManager component
  3. Add entry type cards with edit/delete buttons
  4. Create EditEntryTypeModal
  5. Create DeleteConfirmDialog
  6. Add link from settings page

Phase 3: Reordering (Enhancement)

  1. Add up/down buttons (simple approach)
  2. OR implement drag-and-drop (better UX)
  3. Update API to handle reorder requests
  4. Update release form to respect order

Phase 4: Polish

  1. Add loading states
  2. Add error handling
  3. Add success toasts
  4. Responsive design
  5. Accessibility (keyboard nav, screen readers)

Edge Cases

1. Deleting a type in use

Decision: Block deletion with clear error

  • Show usage count: "Cannot delete. 12 items use this type."
  • Future: Add "Convert items to another type" feature

2. Editing default types

Decision: Disable edit/delete for defaults

  • Mark as "Default" badge
  • Gray out edit button
  • Show tooltip: "Default types can't be modified"

3. Duplicate names during edit

Decision: Check case-insensitively

  • Show error: "A type named 'Added' already exists"
  • Don't allow save until name is unique

4. Reordering default types

Decision: Allow reordering defaults within changelog context

  • Each changelog can have custom order
  • Doesn't affect other changelogs

Testing Checklist

  • Can view all entry types (defaults + custom)
  • Can edit custom type name
  • Can edit custom type icon
  • Can edit custom type color
  • Cannot edit default types
  • Can delete custom type (if not in use)
  • Cannot delete default types
  • Cannot delete type in use (shows error)
  • Can reorder types
  • Order persists after page refresh
  • Release form uses new order
  • Public changelog uses new order
  • Embed widget uses new order
  • Duplicate name validation works
  • Unauthorized users can't access
  • Loading states work
  • Error messages are clear
  • Success toasts appear
  • Responsive on mobile

Estimated Time

Total: 6-8 hours

  • Database migration: 30 min
  • API endpoints: 2 hours
  • UI components: 3 hours
  • Reordering feature: 1.5 hours
  • Polish + testing: 1.5 hours

Priority

Medium-High

  • Users have requested this
  • Import bug created duplicates that need cleanup
  • Quality-of-life improvement for custom types
  • Not blocking launch, but valuable post-launch feature

Dependencies

  • None (can implement immediately)
  • Import/export already working
  • Database schema supports custom types

Future Enhancements

  • Convert items from one type to another before deletion
  • Bulk operations (delete multiple types)
  • Type templates/presets
  • Per-type custom styling in public pages
  • Analytics on type usage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment