diff --git a/src/app/build/page.tsx b/src/app/build/page.tsx index 7216a07..9ee7ee4 100644 --- a/src/app/build/page.tsx +++ b/src/app/build/page.tsx @@ -331,27 +331,15 @@ export default function BuildPage() { {/* Search and Filters */}
- {/* Search Row */} -
-
- -
-
- {/* Filters Row */} -
+
{/* Category Dropdown */}
+ handleSort(e.target.value as SortField)} - className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white text-gray-900" > @@ -521,14 +509,11 @@ export default function BuildPage() {
Find Parts -
diff --git a/src/app/builds/page.tsx b/src/app/builds/page.tsx index 28ae0d4..d345715 100644 --- a/src/app/builds/page.tsx +++ b/src/app/builds/page.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import SearchInput from '@/components/SearchInput'; // Sample build data -const sampleBuilds = [ +const sampleMyBuilds = [ { id: '1', name: 'Budget AR-15 Build', @@ -121,18 +121,18 @@ const sampleBuilds = [ } ]; -type BuildStatus = 'completed' | 'in-progress' | 'planning'; +type MyBuildStatus = 'completed' | 'in-progress' | 'planning'; type SortField = 'name' | 'status' | 'totalCost' | 'completedDate'; type SortDirection = 'asc' | 'desc'; -export default function BuildsPage() { +export default function MyBuildsPage() { const [sortField, setSortField] = useState('completedDate'); const [sortDirection, setSortDirection] = useState('desc'); - const [selectedStatus, setSelectedStatus] = useState('all'); + const [selectedStatus, setSelectedStatus] = useState('all'); const [searchTerm, setSearchTerm] = useState(''); // Filter builds - const filteredBuilds = sampleBuilds.filter(build => { + const filteredMyBuilds = sampleMyBuilds.filter(build => { if (selectedStatus !== 'all' && build.status !== selectedStatus) { return false; } @@ -146,7 +146,7 @@ export default function BuildsPage() { }); // Sort builds - const sortedBuilds = [...filteredBuilds].sort((a, b) => { + const sortedMyBuilds = [...filteredMyBuilds].sort((a, b) => { let aValue: any, bValue: any; if (sortField === 'totalCost') { @@ -170,7 +170,7 @@ export default function BuildsPage() { } }); - const getStatusColor = (status: BuildStatus) => { + const getStatusColor = (status: MyBuildStatus) => { switch (status) { case 'completed': return 'bg-green-100 text-green-800'; @@ -183,7 +183,7 @@ export default function BuildsPage() { } }; - const getStatusIcon = (status: BuildStatus) => { + const getStatusIcon = (status: MyBuildStatus) => { switch (status) { case 'completed': return '✓'; @@ -204,14 +204,14 @@ export default function BuildsPage() { }); }; - const getProgressPercentage = (build: typeof sampleBuilds[0]) => { + const getProgressPercentage = (build: typeof sampleMyBuilds[0]) => { return Math.round((build.components.completed / build.components.total) * 100); }; - const totalBuilds = sampleBuilds.length; - const completedBuilds = sampleBuilds.filter(build => build.status === 'completed').length; - const inProgressBuilds = sampleBuilds.filter(build => build.status === 'in-progress').length; - const totalValue = sampleBuilds.reduce((sum, build) => sum + build.totalCost, 0); + const totalMyBuilds = sampleMyBuilds.length; + const completedMyBuilds = sampleMyBuilds.filter(build => build.status === 'completed').length; + const inProgressMyBuilds = sampleMyBuilds.filter(build => build.status === 'in-progress').length; + const totalValue = sampleMyBuilds.reduce((sum, build) => sum + build.totalCost, 0); return (
@@ -228,15 +228,15 @@ export default function BuildsPage() {
-
{totalBuilds}
+
{totalMyBuilds}
Total Builds
-
{completedBuilds}
+
{completedMyBuilds}
Completed
-
{inProgressBuilds}
+
{inProgressMyBuilds}
In Progress
@@ -254,10 +254,10 @@ export default function BuildsPage() {
@@ -269,7 +269,7 @@ export default function BuildsPage() { setSelectedStatus(e.target.value as MyBuildStatus | 'all')} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + > + + + + + +
+ + {/* Sort by */} +
+ + +
+ + {/* Sort Direction */} +
+ + +
+ + {/* New Build Button */} +
+ +
+
+
+
+ + {/* Builds Grid */} +
+ {sortedMyBuilds.length > 0 ? ( +
+ {sortedMyBuilds.map((build) => ( +
+ {/* Build Image */} +
+ {build.name} { + const target = e.target as HTMLImageElement; + target.style.display = 'none'; + target.nextElementSibling?.classList.remove('hidden'); + }} + /> +
+
+
🔫
+
{build.name}
+
+
+
+ + {getStatusIcon(build.status)} {build.status} + +
+
+ + {/* Build Content */} +
+ {/* Build Title and Date */} +
+

{build.name}

+

{build.description}

+
+ {build.status === 'completed' && build.completedDate && `Completed ${formatDate(build.completedDate)}`} + {build.status === 'in-progress' && build.startedDate && `Started ${formatDate(build.startedDate)}`} + {build.status === 'planning' && build.plannedDate && `Planned for ${formatDate(build.plannedDate)}`} +
+
+ + {/* Progress Bar */} +
+
+ Progress + {build.components.completed}/{build.components.total} components +
+
+
+
+
+ + {/* Component Categories */} +
+
+ {Object.entries(build.components.categories).map(([category, count]) => ( + + {category}: {count} + + ))} +
+
+ + {/* Tags */} +
+
+ {build.tags.map((tag) => ( + + {tag} + + ))} +
+
+ + {/* Cost and Actions */} +
+
+ ${build.totalCost.toFixed(2)} +
+
+ + +
+
+
+
+ ))} +
+ ) : ( +
+
+
No builds found
+
Try adjusting your filters or create a new build
+
+
+ )} +
+ + ); +} \ No newline at end of file diff --git a/src/app/parts/page.tsx b/src/app/parts/page.tsx index 57bb679..8246ec1 100644 --- a/src/app/parts/page.tsx +++ b/src/app/parts/page.tsx @@ -3,7 +3,7 @@ import { useState, useEffect } from 'react'; import { useSearchParams } from 'next/navigation'; import { Listbox, Transition } from '@headlessui/react'; -import { ChevronUpDownIcon, CheckIcon, XMarkIcon } from '@heroicons/react/20/solid'; +import { ChevronUpDownIcon, CheckIcon, XMarkIcon, TableCellsIcon, Squares2X2Icon } from '@heroicons/react/20/solid'; import SearchInput from '@/components/SearchInput'; import ProductCard from '@/components/ProductCard'; import RestrictionAlert from '@/components/RestrictionAlert'; @@ -11,6 +11,7 @@ import Tooltip from '@/components/Tooltip'; import Link from 'next/link'; import { mockProducts } from '@/mock/product'; import type { Product } from '@/mock/product'; +import Image from 'next/image'; // Extract unique values for dropdowns const categories = ['All', ...Array.from(new Set(mockProducts.map(part => part.category.name)))]; @@ -464,14 +465,16 @@ export default function Home() {
@@ -496,24 +499,12 @@ export default function Home() { + - - - {sortedParts.map((part) => ( + - - - diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 07e844d..8bc8901 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -10,8 +10,8 @@ export default function Navbar() { const navItems = [ { href: '/parts', label: 'Parts Catalog' }, - { href: '/build', label: 'Build Checklist' }, - { href: '/builds', label: 'My Builds' }, + { href: '/build', label: 'Plan a Build' }, + { href: '/my-builds', label: 'My Builds' }, ]; return (
+ Product + Category handleSort('name')} - > -
- Name - {getSortIcon('name')} -
-
- Brand - - Description - handleSort('price')} @@ -531,29 +522,20 @@ export default function Home() {
+
+ 0 ? (part.images as string[])[0] : '/window.svg'} alt={part.name} width={48} height={48} className="object-contain w-12 h-12" /> +
+
+
{part.name}
+
{part.brand.name}
+
+
{part.category.name} -
- {part.name} -
-
- {part.brand.name} -
-
-
- {part.brand.name} -
-
-
- {part.description} -
-
${Math.min(...part.offers.map(offer => offer.price)).toFixed(2)} @@ -562,7 +544,7 @@ export default function Home() {
- View Details + Add