feat: dynamic categories system, and correct category display in all templates #22

Merged
Klick3R-1 merged 7 commits from feature/dynamic-categories into main 2025-08-03 19:41:09 -04:00
Klick3R-1 commented 2025-07-18 12:47:06 -04:00 (Migrated from github.com)

-Dynamic categories
-Add/delete on settings page

-Dynamic categories -Add/delete on settings page
bscott (Migrated from github.com) reviewed 2025-07-18 12:47:06 -04:00
bscott commented 2025-07-20 16:51:14 -04:00 (Migrated from github.com)

Thanks!, will review for the next release

Thanks!, will review for the next release
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2025-07-20 16:53:24 -04:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull Request Overview

This PR implements a dynamic categories system that replaces hardcoded category strings with a relational database model. The changes enable users to manage custom categories through a new settings interface while updating all templates to display category names correctly.

  • Creates a new Category model with database relationships to Subscriptions
  • Adds full CRUD API endpoints and handlers for category management
  • Updates all templates to use the new category relationship structure

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
templates/subscription-form.html Replaces hardcoded category options with dynamic category dropdown using database records
templates/settings.html Adds category management UI with add/edit/delete functionality
internal/models/category.go Defines new Category model with ID, name, and timestamps
internal/models/subscription.go Updates Subscription model to use CategoryID foreign key instead of category string
internal/repository/category.go Implements repository layer for category CRUD operations
internal/handlers/category.go Adds REST API handlers for category management
cmd/server/main.go Integrates category service and updates dependency injection
## Pull Request Overview This PR implements a dynamic categories system that replaces hardcoded category strings with a relational database model. The changes enable users to manage custom categories through a new settings interface while updating all templates to display category names correctly. - Creates a new Category model with database relationships to Subscriptions - Adds full CRUD API endpoints and handlers for category management - Updates all templates to use the new category relationship structure ### Reviewed Changes Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | templates/subscription-form.html | Replaces hardcoded category options with dynamic category dropdown using database records | | templates/settings.html | Adds category management UI with add/edit/delete functionality | | internal/models/category.go | Defines new Category model with ID, name, and timestamps | | internal/models/subscription.go | Updates Subscription model to use CategoryID foreign key instead of category string | | internal/repository/category.go | Implements repository layer for category CRUD operations | | internal/handlers/category.go | Adds REST API handlers for category management | | cmd/server/main.go | Integrates category service and updates dependency injection | </details>
@ -7,22 +7,24 @@ import (
)
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-20 16:53:23 -04:00

Remove the commented-out code. Dead code should be deleted rather than commented out to improve maintainability.

// (Line removed)
Remove the commented-out code. Dead code should be deleted rather than commented out to improve maintainability. ```suggestion // (Line removed) ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-20 16:53:23 -04:00

The foreign key constraint 'OnDelete:SET NULL' could cause data integrity issues. When a category is deleted, subscriptions will have null category references. Consider using 'OnDelete:RESTRICT' to prevent category deletion when subscriptions exist, or create a default 'Uncategorized' category.

	Category         Category   `json:"category" gorm:"foreignKey:CategoryID;constraint:OnUpdate:CASCADE,OnDelete:RESTRICT;"`
The foreign key constraint 'OnDelete:SET NULL' could cause data integrity issues. When a category is deleted, subscriptions will have null category references. Consider using 'OnDelete:RESTRICT' to prevent category deletion when subscriptions exist, or create a default 'Uncategorized' category. ```suggestion Category Category `json:"category" gorm:"foreignKey:CategoryID;constraint:OnUpdate:CASCADE,OnDelete:RESTRICT;"` ```
@ -0,0 +1,21 @@
{{if .}}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-20 16:53:24 -04:00

The inline JavaScript in the onclick handler is complex and hard to maintain. Consider extracting this logic into a separate JavaScript function for better readability and reusability.

                    <button type="button" onclick="cancelEdit('{{.ID}}')" class="text-gray-500 text-sm ml-1">Cancel</button>
The inline JavaScript in the onclick handler is complex and hard to maintain. Consider extracting this logic into a separate JavaScript function for better readability and reusability. ```suggestion <button type="button" onclick="cancelEdit('{{.ID}}')" class="text-gray-500 text-sm ml-1">Cancel</button> ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-20 16:53:24 -04:00

Similar to the Cancel button, this inline JavaScript should be extracted into a separate function for better maintainability and consistency with the settings.html implementation.

                <button id="edit-btn-{{.ID}}" onclick="toggleEditCategory('{{.ID}}')" class="text-blue-600 hover:text-blue-800 text-sm font-medium">Edit</button>
                <button hx-delete="/api/categories/{{.ID}}" hx-confirm="Delete this category?" hx-target="#categories-list" hx-swap="innerHTML" class="text-red-600 hover:text-red-800 text-sm font-medium">Delete</button>
            </div>
        </div>
    {{end}}
{{else}}
    <div class="text-center py-4 text-gray-500">No categories found.</div>
{{end}} 
<script>
    function toggleEditCategory(categoryId) {
        const editForm = document.getElementById(`edit-category-form-${categoryId}`);
        const categoryName = document.getElementById(`category-name-${categoryId}`);
        const editButton = document.getElementById(`edit-btn-${categoryId}`);
        
        if (editForm && categoryName && editButton) {
            editForm.classList.remove('hidden');
            categoryName.classList.add('hidden');
            editButton.classList.add('hidden');
        }
    }
</script>
Similar to the Cancel button, this inline JavaScript should be extracted into a separate function for better maintainability and consistency with the settings.html implementation. ```suggestion <button id="edit-btn-{{.ID}}" onclick="toggleEditCategory('{{.ID}}')" class="text-blue-600 hover:text-blue-800 text-sm font-medium">Edit</button> <button hx-delete="/api/categories/{{.ID}}" hx-confirm="Delete this category?" hx-target="#categories-list" hx-swap="innerHTML" class="text-red-600 hover:text-red-800 text-sm font-medium">Delete</button> </div> </div> {{end}} {{else}} <div class="text-center py-4 text-gray-500">No categories found.</div> {{end}} <script> function toggleEditCategory(categoryId) { const editForm = document.getElementById(`edit-category-form-${categoryId}`); const categoryName = document.getElementById(`category-name-${categoryId}`); const editButton = document.getElementById(`edit-btn-${categoryId}`); if (editForm && categoryName && editButton) { editForm.classList.remove('hidden'); categoryName.classList.add('hidden'); editButton.classList.add('hidden'); } } </script> ```
@ -591,0 +645,4 @@
}).then(r => r.json()).then(loadCategories);
};
}
});
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-20 16:53:23 -04:00

The CSS classes 'hidden inline' are contradictory. 'hidden' hides the element while 'inline' sets display to inline. Consider using just 'hidden' since the visibility toggle is handled by JavaScript.

                <form id="edit-category-form-${cat.id}" class="hidden">
The CSS classes 'hidden inline' are contradictory. 'hidden' hides the element while 'inline' sets display to inline. Consider using just 'hidden' since the visibility toggle is handled by JavaScript. ```suggestion <form id="edit-category-form-${cat.id}" class="hidden"> ```
bscott commented 2025-07-23 03:25:14 -04:00 (Migrated from github.com)

@Klick3R-1 Any thoughts on the automated reviews, working on including this in this week's release.

@Klick3R-1 Any thoughts on the automated reviews, working on including this in this week's release.
Klick3R-1 commented 2025-07-23 03:30:09 -04:00 (Migrated from github.com)

@bscott Yes, I was planning to go through the suggestions — already accepted a few while on my phone earlier. I also realized I forgot to populate the default categories, so I’ll make sure to add that too. It should improve usability and help avoid confusion for some users.

@bscott Yes, I was planning to go through the suggestions — already accepted a few while on my phone earlier. I also realized I forgot to populate the default categories, so I’ll make sure to add that too. It should improve usability and help avoid confusion for some users.
Klick3R-1 commented 2025-07-24 16:27:16 -04:00 (Migrated from github.com)

Now its resolved, added creation of categories if there are none. also resolved suggestions made by copilot.

Now its resolved, added creation of categories if there are none. also resolved suggestions made by copilot.
bscott commented 2025-07-26 15:58:33 -04:00 (Migrated from github.com)

Thanks @Klick3R-1 , I'll review and test, planning on getting the next release out this weekend.

Thanks @Klick3R-1 , I'll review and test, planning on getting the next release out this weekend.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bscott/subtrackr!22
No description provided.