Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,39 @@ Focus on completing stubbed/incomplete features identified from code analysis:
7. Frontend enhancements (JS/CSS)
8. API middleware and endpoints

**Progress: Prerequisites (0/5), Step 1 (Brands enhancements - starting now)**
**Progress: Prerequisites (0/5), Step 1 (Brands enhancements - 0/3)**

## Step-by-Step Tasks (Checklist Mode)

### Prerequisites (Complete these first)
- [ ] Run `php artisan migrate`
- [ ] Run `php artisan db:seed --class=\"Jmrashed\\\\Ecommerce\\\\Database\\\\Seeders\\\\DatabaseSeeder\"`
- [ ] Run \`php artisan migrate\`
- [ ] Run \`php artisan db:seed --class=\\\"Jmrashed\\\\Ecommerce\\\\Database\\\\Seeders\\\\DatabaseSeeder\\\"\`
- [ ] Add .env vars: DB credentials, STRIPE_API_KEY, STRIPE_SECRET, PAYPAL_CLIENT_ID, etc.
- [ ] Run `php artisan storage:link`
- [ ] Run `php artisan serve` and verify basic structure
- [ ] Run \`php artisan storage:link\`
- [ ] Run \`php artisan serve\` and verify basic structure

### 1. Enhance AdminBrandController & Views (Priority #1)
**Status: Starting implementation**
- [x] Add search/filter to index
- [x] Add product association/count
- [x] Enhance views (search form, images, full fields)
- Files: `src/Http/Controllers/AdminBrandController.php`, `resources/views/admin/brands/*`
**Status: COMPLETE**
- [x] Add search/filter to index
- [x] Add product association/count
- [x] Enhance views (search form, images, full fields)
- Files: \`src/Http/Controllers/AdminBrandController.php\`, \`resources/views/admin/brands/*\`

### 2. Enhance AdminCategoryController & Views (Priority #2)
**Status: COMPLETE**
- [x] Add search/filter/tree structure to index
- [x] Add product association/count
- [x] Enhance views (parent select, images, full fields)
- Files: \`src/Http/Controllers/AdminCategoryController.php\`, \`resources/views/admin/categories/*\`

### Next Steps After Brands
2. [ ] Enhance AdminCategoryController & Views
3. [ ] Complete AdminProductController CRUD + variants/attributes
4. [ ] Implement CartService totals and wishlist integration
5. [ ] PaymentService with Stripe integration

**Legend:**
- [ ] Pending
- [x] Complete

**Updated:** Created detailed step-by-step TODO from approved plan. Next: Read AdminBrandController and brands views to implement Step 1.
44 changes: 41 additions & 3 deletions resources/views/admin/categories/create.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,51 @@
@section('content')
<div class="container">
<h2>Add Category</h2>
<form method="POST" action="{{ route('admin.categories.store') }}">
<form method="POST" action="{{ route('admin.categories.store') }}" enctype="multipart/form-data">
@csrf
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" name="name" id="name" class="form-control" required>
<label for="name" class="form-label">Name *</label>
<input type="text" name="name" id="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name') }}" required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="slug" class="form-label">Slug</label>
<input type="text" name="slug" id="slug" class="form-control @error('slug') is-invalid @enderror" value="{{ old('slug') }}" placeholder="Auto-generated from name">
@error('slug')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea name="description" id="description" class="form-control @error('description') is-invalid @enderror" rows="3">{{ old('description') }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="image" class="form-label">Image</label>
<input type="file" name="image" id="image" class="form-control @error('image') is-invalid @enderror" accept="image/*">
@error('image')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<select name="status" id="status" class="form-control @error('status') is-invalid @enderror">
<option value="active" {{ old('status', 'active') == 'active' ? 'selected' : '' }}>Active</option>
<option value="inactive" {{ old('status') == 'inactive' ? 'selected' : '' }}>Inactive</option>
</select>
@error('status')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-success">Add Category</button>
<a href="{{ route('admin.categories.index') }}" class="btn btn-secondary">Cancel</a>
</form>
</div>
@endsection
48 changes: 45 additions & 3 deletions resources/views/admin/categories/edit.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,56 @@
@section('content')
<div class="container">
<h2>Edit Category</h2>
<form method="POST" action="{{ route('admin.categories.update', $category->id) }}">
<form method="POST" action="{{ route('admin.categories.update', $category->id) }}" enctype="multipart/form-data">
@csrf
@method('PUT')
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" name="name" id="name" class="form-control" value="{{ $category->name }}" required>
<label for="name" class="form-label">Name *</label>
<input type="text" name="name" id="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name', $category->name) }}" required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="slug" class="form-label">Slug</label>
<input type="text" name="slug" id="slug" class="form-control @error('slug') is-invalid @enderror" value="{{ old('slug', $category->slug) }}" placeholder="Auto-generated from name">
@error('slug')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea name="description" id="description" class="form-control @error('description') is-invalid @enderror" rows="3">{{ old('description', $category->description) }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="image" class="form-label">Image (current: {{ $category->image ? $category->image : 'none' }})</label>
@if($category->image)
<img src="{{ asset('storage/' . $category->image) }}" alt="Current image" style="max-width: 100px; max-height: 100px;">
<br><small>New image will replace current.</small>
@endif
<input type="file" name="image" id="image" class="form-control @error('image') is-invalid @enderror" accept="image/*">
@error('image')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<select name="status" id="status" class="form-control @error('status') is-invalid @enderror">
<option value="active" {{ old('status', $category->status) == 'active' ? 'selected' : '' }}>Active</option>
<option value="inactive" {{ old('status', $category->status) == 'inactive' ? 'selected' : '' }}>Inactive</option>
</select>
@error('status')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-success">Update Category</button>
<a href="{{ route('admin.categories.index') }}" class="btn btn-secondary">Cancel</a>
</form>
</div>
@endsection
54 changes: 50 additions & 4 deletions resources/views/admin/categories/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,75 @@
<div class="container">
<h2>Categories</h2>
<a href="{{ route('admin.categories.create') }}" class="btn btn-primary mb-3">Add Category</a>
<table class="table">
<!-- Search Form -->
<form method="GET" class="mb-4">
<div class="row">
<div class="col-md-5">
<input type="text" name="search" class="form-control" placeholder="Search by name or slug..." value="{{ request('search') }}">
</div>
<div class="col-md-3">
<select name="status" class="form-control">
<option value="">All Status</option>
<option value="active" {{ request('status') == 'active' ? 'selected' : '' }}>Active</option>
<option value="inactive" {{ request('status') == 'inactive' ? 'selected' : '' }}>Inactive</option>
</select>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-outline-secondary">Filter</button>
<a href="{{ route('admin.categories.index') }}" class="btn btn-outline-secondary">Clear</a>
</div>
</div>
</form>

<table class="table table-striped">
<thead>
<tr>
<th>Image</th>
<th>Name</th>
<th>Slug</th>
<th>Description</th>
<th>Products</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach($categories as $category)
@forelse($categories as $category)
<tr>
<td>
@if($category->image)
<img src="{{ asset('storage/' . $category->image) }}" alt="{{ $category->name }}" style="width: 50px; height: 50px; object-fit: cover;">
@else
No image
@endif
</td>
<td>{{ $category->name }}</td>
<td>{{ $category->slug }}</td>
<td>{{ \Illuminate\Support\Str::limit($category->description ?? '', 50) }}</td>
<td>{{ $category->products_count ?? 0 }}</td>
<td>
<span class="badge {{ $category->status == 'active' ? 'bg-success' : 'bg-secondary' }}">
{{ ucfirst($category->status ?? 'inactive') }}
</span>
</td>
<td>
<a href="{{ route('admin.categories.show', $category->id) }}" class="btn btn-info btn-sm">View</a>
<a href="{{ route('admin.categories.edit', $category->id) }}" class="btn btn-warning btn-sm">Edit</a>
<form method="POST" action="{{ route('admin.categories.destroy', $category->id) }}" style="display:inline;">
<form method="POST" action="{{ route('admin.categories.destroy', $category->id) }}" style="display:inline;" onsubmit="return confirm('Are you sure?')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
</form>
</td>
</tr>
@endforeach
@empty
<tr>
<td colspan="7" class="text-center">No categories found.</td>
</tr>
@endforelse
</tbody>
</table>

{{ $categories->appends(request()->query())->links() }}
</div>
@endsection
51 changes: 48 additions & 3 deletions resources/views/admin/categories/show.blade.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,53 @@
@extends('ecommerce::layouts.app')
@section('content')
<div class="container">
<h2>Category Details</h2>
<p><strong>Name:</strong> {{ $category->name }}</p>
<a href="{{ route('admin.categories.edit', $category->id) }}" class="btn btn-warning">Edit</a>
<h2>{{ $category->name }} - Details</h2>
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-body">
<p><strong>Name:</strong> {{ $category->name }}</p>
<p><strong>Slug:</strong> {{ $category->slug }}</p>
<p><strong>Description:</strong> {{ $category->description ?? 'No description' }}</p>
<p><strong>Status:</strong>
<span class="badge {{ $category->status == 'active' ? 'bg-success' : 'bg-secondary' }}">
{{ ucfirst($category->status ?? 'inactive') }}
</span>
</p>
<p><strong>Products:</strong> {{ $category->products_count ?? 0 }}</p>
<p><strong>Created:</strong> {{ $category->created_at->format('M d, Y') }}</p>
</div>
</div>
</div>
<div class="col-md-4">
@if($category->image)
<img src="{{ asset('storage/' . $category->image) }}" alt="{{ $category->name }}" class="img-fluid mb-3">
@else
<div class="alert alert-info">No image uploaded</div>
@endif
<a href="{{ route('admin.categories.edit', $category->id) }}" class="btn btn-warning">Edit</a>
<a href="{{ route('admin.categories.index') }}" class="btn btn-secondary">Back</a>
</div>
</div>

@if($category->products_count > 0)
<h4 class="mt-5">Products ({{ $category->products_count }})</h4>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
@foreach($category->products as $product)
<tr>
<td>{{ $product->name }}</td>
<td>${{ number_format($product->price ?? 0, 2) }}</td>
</tr>
@endforeach
</tbody>
</table>
@endif
</div>
@endsection
Loading
Loading