refactor(frontend): centralize category list for tabs and seeding#67
Conversation
✅ Deploy Preview for develop-devlovers ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
WalkthroughThis PR refactors the frontend to centralize category definitions into a new data module. It introduces Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10–15 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
frontend/data/categories.ts (1)
1-9: Consider making the array readonly for immutability.The
categoryNamesarray serves as a single source of truth and should be protected from accidental mutations. Consider usingas constassertion for better type safety.🔎 Proposed fix to add const assertion
-export const categoryNames = [ +export const categoryNames = [ 'HTML', 'CSS', 'JavaScript', 'React', 'Angular', 'Vue', 'Next', -]; +] as const;This will:
- Make the array readonly at the type level
- Narrow the type from
string[]to a tuple of literal types- Prevent accidental mutations like
categoryNames.push('Svelte')
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
frontend/app/layout.tsx(1 hunks)frontend/components/shared/TabsSection.tsx(5 hunks)frontend/data/categories.ts(1 hunks)frontend/db/seed-categories.ts(1 hunks)frontend/package.json(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/db/seed-categories.ts (2)
frontend/data/categories.ts (1)
categoryNames(1-9)frontend/db/index.ts (1)
db(17-17)
🔇 Additional comments (8)
frontend/app/layout.tsx (1)
29-29: LGTM - Standard formatting convention.The trailing newline after the closing brace follows standard file formatting conventions.
frontend/db/seed-categories.ts (2)
5-5: LGTM - Centralized category data source.Importing
categoryNamesfrom the shared data module eliminates hardcoded duplication and ensures consistency across seeding and UI components.
7-15: LGTM - Improved function naming and data source.The function rename from
maintocategoriesListis more descriptive, and iterating over the importedcategoryNamesmaintains the same logic while using the centralized category definition.frontend/components/shared/TabsSection.tsx (4)
29-35: LGTM - Consistent URL handling and state initialization.The URL parameter extraction and initial state logic correctly use
DEFAULT_CATEGORYas the fallback, with proper validation to ensure only valid categories are set as active.
45-63: LGTM - Clean URL strategy by excluding default values.The
updateUrlfunction correctly excludes the default category from URL parameters, keeping URLs clean and consistent with the pattern of excluding other defaults (page 1, empty search).
161-166: LGTM - Grid layout matches category count.The grid layout correctly expands from 5 to 7 columns to accommodate the 7 categories defined in
categoryNames. Removing thecapitalizeclass is appropriate since category names in the source data are already properly cased.
178-182: LGTM - Appropriate conditional messaging.The conditional rendering correctly displays different messages based on whether a search query is active, providing clear feedback to users in both scenarios.
frontend/package.json (1)
13-13: No action required. The parse script pathparse/parse.tsis correctly updated and the file exists at the specified location.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/components/shared/TabsSection.tsx(5 hunks)frontend/data/categories.ts(1 hunks)frontend/db/seed.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/components/shared/TabsSection.tsx
🔇 Additional comments (1)
frontend/db/seed.ts (1)
9-9: LGTM! The relocated parse output path is correctly updated.The import path in
frontend/db/seed.tsline 9 has been successfully updated to../parse/questions.json, the new file exists atfrontend/parse/questions.json, and no lingering references to the old path remain in the codebase.
| export const categories = [ | ||
| 'HTML', | ||
| 'CSS', | ||
| 'JavaScript', | ||
| 'React', | ||
| 'Angular', | ||
| 'Vue', | ||
| 'Next', | ||
| ]; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, check the structure of the frontend directory
echo "=== Directory structure ==="
git ls-files frontend/ | head -20
echo -e "\n=== Content of frontend/data/categories.ts ==="
cat -n frontend/data/categories.ts
echo -e "\n=== Search for hardcoded category arrays ==="
# Look for array literals containing category names
rg -n --type=ts --type=tsx "(\[.*HTML.*CSS|React.*Vue)" frontend/ -g '!frontend/data/categories.ts' | head -20
echo -e "\n=== Search for imports from categories ==="
rg -n --type=ts --type=tsx "from.*categories|import.*categories" frontend/ | head -20
echo -e "\n=== Search for hardcoded category strings together ==="
rg -n --type=ts --type=tsx "'HTML'.*'CSS'|'React'.*'Vue'|'Angular'" frontend/ -g '!frontend/data/categories.ts' | head -30Repository: DevLoversTeam/devlovers.net
Length of output: 1260
🏁 Script executed:
#!/bin/bash
# Look for any mentions of the specific category names together
echo "=== Searching for potential duplicate category definitions ==="
rg -n "HTML|CSS|JavaScript|React|Angular|Vue|Next" frontend/ --type ts --type tsx | grep -E "\[|const|export" | head -30Repository: DevLoversTeam/devlovers.net
Length of output: 178
🏁 Script executed:
#!/bin/bash
# Get the exact content and check for imports
echo "=== categories.ts content ==="
cat frontend/data/categories.ts
echo -e "\n=== Check for other data files in frontend/data ==="
ls -la frontend/data/ 2>/dev/null || echo "Directory not found"
echo -e "\n=== Search for files that import from categories ==="
rg --type=ts --type=tsx "from.*categories|import.*categories" frontend/ 2>/dev/null || echo "No imports found"
echo -e "\n=== Search for hardcoded arrays with category keywords ==="
rg -B2 -A8 "'HTML'" frontend/ --type=ts --type=tsx -g '!categories.ts' 2>/dev/null | head -50Repository: DevLoversTeam/devlovers.net
Length of output: 567
🏁 Script executed:
#!/bin/bash
# Broader search without type flags for files with category keywords
echo "=== Search for files mentioning category names ==="
rg -n "TabsSection|seed-categories" frontend/ 2>/dev/null || echo "Files not found"
echo -e "\n=== Search for exports/definitions with category-like patterns ==="
rg -n "export.*\[" frontend/ --max-count 20 | head -30
echo -e "\n=== Look for arrays containing HTML ==="
rg -n -B2 -A6 "HTML" frontend/ -g '!categories.ts' 2>/dev/null | head -50
echo -e "\n=== Check all TypeScript/TSX files in frontend ==="
find frontend -name "*.ts" -o -name "*.tsx" | wc -l
echo -e "\n=== Search for category-related code ==="
rg -n "category\|categories" frontend/ -i 2>/dev/null | grep -v categories.ts | head -20Repository: DevLoversTeam/devlovers.net
Length of output: 6249
🏁 Script executed:
#!/bin/bash
# Check the existing CATEGORIES in catalog.ts
echo "=== Content of frontend/lib/config/catalog.ts (first 60 lines) ==="
head -60 frontend/lib/config/catalog.ts
echo -e "\n=== Look for seed-categories.ts ==="
find . -name "seed-categories.ts" -o -name "*seed*categories*" 2>/dev/null
echo -e "\n=== Check database directory ==="
ls -la db/ 2>/dev/null | head -20Repository: DevLoversTeam/devlovers.net
Length of output: 1929
🏁 Script executed:
#!/bin/bash
# Check the seed-categories.ts file
echo "=== Content of frontend/db/seed-categories.ts ==="
cat frontend/db/seed-categories.ts
echo -e "\n=== Check TabsSection.tsx ==="
cat frontend/components/shared/TabsSection.tsxRepository: DevLoversTeam/devlovers.net
Length of output: 6638
🏁 Script executed:
#!/bin/bash
# Double-check the exact exports and imports
echo "=== Exact exports from categories.ts ==="
grep "export" frontend/data/categories.ts
echo -e "\n=== Exact imports in seed-categories.ts ==="
grep "import\|from" frontend/db/seed-categories.ts | head -5
echo -e "\n=== Check if categoryNames is defined elsewhere ==="
rg "categoryNames|export.*categoryNames" frontend/Repository: DevLoversTeam/devlovers.net
Length of output: 534
Fix import mismatch in seed-categories.ts—currently cannot export a non-existent categoryNames.
The centralization successfully eliminates duplication in TabsSection.tsx, which correctly imports categories from the new module. However, seed-categories.ts attempts to import categoryNames from ../data/categories, which does not exist. The export is named categories, not categoryNames. This will cause the seed script to fail at runtime.
Change the import in seed-categories.ts from:
import { categoryNames } from '../data/categories';to:
import { categories } from '../data/categories';🤖 Prompt for AI Agents
In frontend/data/categories.ts lines 1-9: the module exports a named export
called "categories" but seed-categories.ts imports a non-existent
"categoryNames"; update seed-categories.ts to import the correct named export
"categories" from '../data/categories' (replace the import of categoryNames with
categories) so the seed script uses the existing export.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
frontend/data/category.ts (1)
1-9: Consider making the array immutable withas const.Adding
as constassertion would provide better type safety by making the array readonly and narrowing the types to literal values, preventing accidental modifications.🔎 Proposed refactor
-export const categoryNames = [ +export const categoryNames = [ 'HTML', 'CSS', 'JavaScript', 'React', 'Angular', 'Vue', 'Next', -]; +] as const;Then you could derive a type like
type CategoryName = typeof categoryNames[number]for type-safe usage elsewhere.frontend/components/shared/TabsSection.tsx (1)
160-166: Consider making grid columns dynamic.The
grid-cols-7class is hardcoded to match the current number of categories. If categories are added or removed fromcategoryNames, this class needs manual synchronization. Consider making it dynamic to improve maintainability.🔎 Potential approaches
Option 1: Use Tailwind's arbitrary value syntax
- <TabsList className="grid grid-cols-7 mb-6"> + <TabsList className={`grid grid-cols-[repeat(${categoryNames.length},minmax(0,1fr))] mb-6`}>Option 2: Use inline style
- <TabsList className="grid grid-cols-7 mb-6"> + <TabsList + className="grid mb-6" + style={{ gridTemplateColumns: `repeat(${categoryNames.length}, minmax(0, 1fr))` }} + >Option 3: Define dynamic Tailwind classes (if you have a safelist in tailwind.config)
Create a helper function or ensure Tailwind JIT can handle the dynamic class.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/components/shared/TabsSection.tsx(5 hunks)frontend/data/category.ts(1 hunks)frontend/db/seed-categories.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/db/seed-categories.ts
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/components/shared/TabsSection.tsx (1)
frontend/data/category.ts (1)
categoryNames(1-9)
🔇 Additional comments (4)
frontend/components/shared/TabsSection.tsx (4)
11-13: LGTM! Centralized category import.The import and DEFAULT_CATEGORY definition look good. The fallback value correctly matches the first category in the array, addressing the previous review comment.
44-62: Verify the default category change is intentional.The URL omission logic now treats 'HTML' as the default category instead of 'react'. This means:
- URLs without a category parameter now default to 'HTML' (previously 'react')
- The category parameter is omitted for 'HTML' instead of 'react'
This is a breaking change that affects existing bookmarks, shared links, and search engine indexed pages. While this appears aligned with the PR's centralization goals, please confirm:
- This behavior change is intentional
- Any necessary migration or user communication has been planned
- Analytics/monitoring is in place to track impact
161-184: LGTM! Clean dynamic rendering.The dynamic rendering of tabs using
categoryNames.map()is well-implemented. The code correctly:
- Uses category names as unique keys
- Displays properly capitalized category names
- Handles loading, results, and empty states appropriately
28-34: LGTM! Robust URL parameter validation.The validation logic correctly checks that the category from the URL exists in
categoryNamesbefore using it, falling back toDEFAULT_CATEGORYif invalid. This provides good protection against URL manipulation.
refactor(frontend): centralize category list for tabs and seeding
Refactor: Centralize Category List for Tabs and Seeding
Overview
This pull request refactors category handling on the frontend by centralizing the category source used across the application.
Previously, category lists were duplicated in multiple places, which caused inconsistencies when adding or updating categories. This change ensures that tabs rendering and database seeding stay in sync by relying on a single shared category definition.
What Was Changed
Summary by CodeRabbit
Style
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.