137 lines
4.6 KiB
PHP
137 lines
4.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Category;
|
|
use App\Models\Color;
|
|
use App\Models\CustomRequest;
|
|
use App\Models\Material;
|
|
use App\Models\Product;
|
|
use Illuminate\Http\Request;
|
|
|
|
class ShopController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
$categories = Category::where('is_featured', true)
|
|
->orderBy('sort_order')
|
|
->take(6)
|
|
->get();
|
|
|
|
$featuredProducts = Product::with('category')
|
|
->published()
|
|
->where('is_featured', true)
|
|
->latest()
|
|
->take(6)
|
|
->get();
|
|
|
|
$materials = Material::where('is_active', true)->get();
|
|
|
|
return view('shop.index', compact('categories', 'featuredProducts', 'materials'));
|
|
}
|
|
|
|
public function catalog(Request $request)
|
|
{
|
|
$query = Product::with('category')->published();
|
|
|
|
// Filter op categorie
|
|
if ($request->filled('category')) {
|
|
$query->whereHas('category', function ($q) use ($request) {
|
|
$q->where('slug', $request->category);
|
|
});
|
|
}
|
|
|
|
// Filter op materiaal
|
|
if ($request->filled('material')) {
|
|
$query->whereJsonContains('available_materials', $request->material);
|
|
}
|
|
|
|
// Zoekfunctie
|
|
if ($request->filled('q')) {
|
|
$search = $request->q;
|
|
$query->where(function ($q) use ($search) {
|
|
$q->where('name', 'like', "%{$search}%")
|
|
->orWhere('short_description', 'like', "%{$search}%")
|
|
->orWhere('description', 'like', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
// Sortering
|
|
$sort = $request->get('sort', 'newest');
|
|
if ($sort === 'price_asc') {
|
|
$query->orderBy('base_price', 'asc');
|
|
} elseif ($sort === 'price_desc') {
|
|
$query->orderBy('base_price', 'desc');
|
|
} else {
|
|
$query->latest();
|
|
}
|
|
|
|
$products = $query->paginate(12)->withQueryString();
|
|
$categories = Category::orderBy('name')->get();
|
|
$materials = Material::where('is_active', true)->get();
|
|
|
|
return view('shop.catalog', compact('products', 'categories', 'materials'));
|
|
}
|
|
|
|
public function show($slug)
|
|
{
|
|
$product = Product::with('category')->published()->where('slug', $slug)->firstOrFail();
|
|
$allMaterials = Material::where('is_active', true)->get()->keyBy('code');
|
|
$allColors = Color::where('in_stock', true)->get();
|
|
|
|
$relatedProducts = Product::published()
|
|
->where('id', '!=', $product->id)
|
|
->where('category_id', $product->category_id)
|
|
->take(3)
|
|
->get();
|
|
|
|
return view('shop.show', compact('product', 'allMaterials', 'allColors', 'relatedProducts'));
|
|
}
|
|
|
|
public function customRequest()
|
|
{
|
|
$materials = Material::where('is_active', true)->get();
|
|
$colors = Color::where('in_stock', true)->get();
|
|
|
|
return view('shop.custom', compact('materials', 'colors'));
|
|
}
|
|
|
|
public function storeCustomRequest(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'email' => 'required|email|max:255',
|
|
'phone' => 'nullable|string|max:50',
|
|
'description' => 'required|string|max:2000',
|
|
'preferred_material' => 'nullable|string|max:50',
|
|
'preferred_color' => 'nullable|string|max:50',
|
|
'dimensions' => 'nullable|string|max:100',
|
|
'model_file' => 'nullable|file|max:51200', // max 50MB (stl, step, obj, zip)
|
|
]);
|
|
|
|
$filePath = null;
|
|
$originalName = null;
|
|
|
|
if ($request->hasFile('model_file')) {
|
|
$file = $request->file('model_file');
|
|
$originalName = $file->getClientOriginalName();
|
|
$filePath = $file->store('custom_models', 'public');
|
|
}
|
|
|
|
CustomRequest::create([
|
|
'name' => $validated['name'],
|
|
'email' => $validated['email'],
|
|
'phone' => $validated['phone'] ?? null,
|
|
'description' => $validated['description'],
|
|
'preferred_material' => $validated['preferred_material'] ?? null,
|
|
'preferred_color' => $validated['preferred_color'] ?? null,
|
|
'dimensions' => $validated['dimensions'] ?? null,
|
|
'file_path' => $filePath,
|
|
'original_filename' => $originalName,
|
|
'status' => 'nieuw',
|
|
]);
|
|
|
|
return redirect()->route('custom.request')->with('success', 'Bedankt! Jouw 3D print aanvraag is succesvol ontvangen. We beoordelen je model en sturen binnen 24 uur een vrijblijvende prijsopgave.');
|
|
}
|
|
}
|