VINLAB Project Details and Handover Guide ========================================= Project Summary --------------- VINLAB is a Laravel catalog and lead-generation website for: - Nursing and medical training products - Laboratory equipment - Education maps, charts, globes, models, and GIS learning products The public website shows home pages, product listings, product detail pages, services, industries, blog, contact, and quote forms. The admin dashboard manages categories, products, media, services, blog posts, inquiries, and site settings. Local Environment ----------------- Project path: - c:\xampp\htdocs\vinlab-laravel Main local URL: - http://127.0.0.1:8000 Common local command: - php artisan serve Database from .env: - DB_CONNECTION=mysql - DB_HOST=127.0.0.1 - DB_PORT=3306 - DB_DATABASE=vinlab - DB_USERNAME=root - DB_PASSWORD is blank Admin Access ------------ Admin login URL: - http://127.0.0.1:8000/admin/login Current admin credentials from .env: - Username: admin - Password: admin123 Important: - This project does not currently use the users table for admin login. - Admin login is handled by app/Http/Controllers/AdminController.php using ADMIN_USERNAME and ADMIN_PASSWORD_HASH from .env. - Admin session access is checked by app/Http/Middleware/EnsureVinlabAdmin.php. How to change admin username: 1. Open .env. 2. Change: ADMIN_USERNAME=admin How to change admin password: 1. Generate a new bcrypt hash: php -r "echo password_hash('your-new-password', PASSWORD_BCRYPT), PHP_EOL;" 2. Copy the generated hash. 3. Update .env: ADMIN_PASSWORD_HASH=generated-hash-here 4. Clear config cache: php artisan optimize:clear There is no database table to edit for the current admin login credentials. Site Settings ------------- Admin settings page: - /admin/settings Settings include: - Site name - Tagline - Admin email - Footer phone/email/about/social links - Logo - Favicon - Virtual tour image/text - Map title/address/embed URL Storage location: - storage/app/site-settings.json This is not stored in a database table right now. The public layout reads these settings through the shared siteSettings data. Main File Structure ------------------- Routes: - routes/web.php Frontend controller: - app/Http/Controllers/FrontendController.php Admin controller: - app/Http/Controllers/AdminController.php Models: - app/Models/Category.php - app/Models/Product.php - app/Models/Service.php - app/Models/BlogPost.php - app/Models/Inquiry.php Public views: - resources/views/public/home.blade.php - resources/views/public/home-2.blade.php - resources/views/public/home-3.blade.php - resources/views/public/about.blade.php - resources/views/public/products.blade.php - resources/views/public/product-detail.blade.php - resources/views/public/services.blade.php - resources/views/public/service-detail.blade.php - resources/views/public/industries.blade.php - resources/views/public/blog.blade.php - resources/views/public/blog-detail.blade.php - resources/views/public/contact.blade.php - resources/views/public/quote.blade.php Product detail components: - resources/views/components/product/type1.blade.php - resources/views/components/product/type2.blade.php - resources/views/components/product/type3.blade.php Admin views: - resources/views/admin/dashboard.blade.php - resources/views/admin/categories.blade.php - resources/views/admin/products.blade.php - resources/views/admin/product-form.blade.php - resources/views/admin/media.blade.php - resources/views/admin/settings.blade.php - resources/views/admin/services.blade.php - resources/views/admin/blog.blade.php - resources/views/admin/inquiries.blade.php Shared layouts: - resources/views/layouts/public.blade.php - resources/views/layouts/admin.blade.php Shared partials: - resources/views/partials/product-card.blade.php - resources/views/partials/inquiry-form.blade.php Main CSS: - public/assets/css/styles.css Main JavaScript: - public/assets/js/app.js Uploaded media: - public/assets/uploads/products - public/assets/uploads/branding - public/assets/uploads/virtual-tour Database Structure ------------------ Main migrations: - database/migrations/2026_04_29_000003_create_vinlab_catalog_tables.php - database/migrations/2026_04_29_000004_add_multi_type_product_fields.php - database/migrations/2026_04_30_000001_add_soft_deletes_to_admin_content.php Main tables: - categories - products - services - blog_posts - inquiries categories table: - id - parent_id - name - slug - description - image_url - meta_title - meta_description - sort_order - created_at - deleted_at, if soft delete migration has run products table: - id - category_id - product_type - name - slug - short_description - description - price - stock - features - specification_pairs - faq - gallery_type - catalog_items - enable_cart - status - specifications - use_cases - images - brochure_url - meta_title - meta_description - is_featured - created_at - updated_at - deleted_at services table: - id - title - slug - summary - overview - offer_items - process_items - industries - image_url - meta_title - meta_description - deleted_at blog_posts table: - id - title - slug - category - excerpt - body - image_url - meta_title - meta_description - published_at - deleted_at inquiries table: - id - product_id - name - organization - email - phone - category - requirement - message - source_page - status - created_at - deleted_at Product Category Model ---------------------- There are 3 main parent categories: - Nursing and Medical - Laboratory - Education Maps and Charts Products must be assigned to a child category under one of those parents. Public product domain filters are defined in: - app/Http/Controllers/FrontendController.php Look for: - public function products(Request $request) - $domainGroups Admin product category selection is in: - resources/views/admin/product-form.blade.php Product Types ------------- type1: E-commerce style - Price - Stock - Add to cart - Buy now - Features - Specifications type2: Inquiry style - Request quote - Features - Specification rows - FAQ type3: Catalog style - Gallery display - Grouped catalog item list - Catalog item images Frontend product detail selection: - resources/views/public/product-detail.blade.php Components: - type1: resources/views/components/product/type1.blade.php - type2: resources/views/components/product/type2.blade.php - type3: resources/views/components/product/type3.blade.php How to Add a New Public Page ---------------------------- Example: Add a new page called Certifications. 1. Add a route in routes/web.php: Route::get('/certifications', [FrontendController::class, 'certifications'])->name('certifications'); 2. Add a method in app/Http/Controllers/FrontendController.php: public function certifications(): View { return view('public.certifications'); } 3. Create the Blade file: resources/views/public/certifications.blade.php 4. Use the public layout: @extends('layouts.public') @section('content')

VINLAB

Certifications

Page description here.

@endsection 5. Add the nav link in: resources/views/layouts/public.blade.php 6. Add CSS in: public/assets/css/styles.css How to Add a New Admin Page --------------------------- 1. Add routes inside the admin route group in routes/web.php. 2. Add methods in app/Http/Controllers/AdminController.php. 3. Create a view in resources/views/admin. 4. Add a sidebar link in resources/views/layouts/admin.blade.php. 5. If database storage is needed, create a migration and model. Media and Image Uploads ----------------------- Admin media page: - /admin/media Upload handling: - app/Http/Controllers/AdminController.php - uploadMedia() - storePublicUpload() Product form media gallery: - resources/views/admin/product-form.blade.php - public/assets/js/app.js Uploaded product images are usually stored under: - public/assets/uploads/products Logo and favicon uploads are stored under: - public/assets/uploads/branding Inquiry and Cart Flow --------------------- Public forms post to: - POST /inquiry Route name: - inquiry.store Controller method: - FrontendController::inquiry() Inquiry data is saved in: - inquiries table Admin page: - /admin/inquiries Cart behavior: - Cart items are stored in browser localStorage as vinlab_cart. - Cart UI and checkout drawer are in resources/views/layouts/public.blade.php. - Cart JavaScript is in public/assets/js/app.js. - Cart details are submitted into the inquiry message through the hidden cart_details field. Email notifications: - The current .env uses MAIL_MAILER=log, so emails are logged instead of sent. - To send real email, update MAIL_* settings in .env. - Recipient is taken from admin_email in site settings, falling back to config mail from address. Useful SQL Commands ------------------- Show parent categories: SELECT id, name, slug FROM categories WHERE parent_id IS NULL AND deleted_at IS NULL ORDER BY sort_order, name; Show child categories with parent: SELECT c.id, p.name AS parent, c.name, c.slug FROM categories c LEFT JOIN categories p ON p.id = c.parent_id WHERE c.parent_id IS NOT NULL AND c.deleted_at IS NULL ORDER BY p.name, c.name; Show latest products: SELECT id, name, slug, product_type, category_id, status, is_featured, updated_at FROM products WHERE deleted_at IS NULL ORDER BY updated_at DESC LIMIT 20; Mark a product as featured: UPDATE products SET is_featured = 1 WHERE id = 1; Deactivate a product: UPDATE products SET status = 'draft' WHERE id = 1; Restore a soft-deleted product: UPDATE products SET deleted_at = NULL WHERE id = 1; Show latest inquiries: SELECT id, name, organization, email, phone, status, created_at FROM inquiries ORDER BY created_at DESC LIMIT 20; Mark an inquiry as contacted: UPDATE inquiries SET status = 'contacted' WHERE id = 1; Update a product slug: UPDATE products SET slug = 'new-product-slug' WHERE id = 1; Maintenance Commands -------------------- Clear Laravel caches: php artisan optimize:clear Compile Blade views: php artisan view:cache Run migrations: php artisan migrate Run all seeders: php artisan db:seed Run a specific seeder: php artisan db:seed --class=LaboratoryProductSeeder Check routes: php artisan route:list Design Notes ------------ Most visual styling is currently in: - public/assets/css/styles.css This file has many override sections because the site has gone through several design revisions. When making a new design fix, add the final override near the bottom of the file or carefully check whether a later CSS rule is overriding your change. JavaScript Notes ---------------- Main JavaScript file: - public/assets/js/app.js Current responsibilities: - Mobile menu - Product gallery thumbnail switching - Product filter tabs - Admin product type panels - Admin product form tabs - Admin media popup selection - Cart localStorage behavior - Quote modal - Virtual tour drag behavior Recommended Rules for Future Work --------------------------------- - Add new public content in resources/views/public. - Add reusable UI blocks in resources/views/components. - Keep admin features in resources/views/admin and AdminController. - Keep public website behavior in FrontendController. - Use slugs for public URLs. - Keep products under the 3 parent category structure. - After changing routes, views, or config, run php artisan optimize:clear. - After Blade edits, run php artisan view:cache to catch template errors.