404
25 |Oops, something went wrong.
26 |Sorry, we couldn't find your page.
27 |├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── README.md ├── app ├── Http │ ├── Controllers │ │ └── Controller.php │ └── Middleware │ │ └── AdminMiddleware.php ├── Livewire │ ├── AboutUs.php │ ├── AddCategory.php │ ├── AddProductForm.php │ ├── AdminDashboard.php │ ├── AllProducts.php │ ├── BreadCrumb.php │ ├── Contacts.php │ ├── EditProduct.php │ ├── Footer.php │ ├── Header.php │ ├── HeroSection.php │ ├── ItemCard.php │ ├── ManageCategories.php │ ├── ManageOrders.php │ ├── ManageProduct.php │ ├── ProductDetails.php │ ├── ProductListing.php │ ├── ProductSection.php │ ├── ProductTable.php │ ├── ShoppingCartComponent.php │ └── ShoppingCartIcon.php ├── Models │ ├── Category.php │ ├── Product.php │ ├── ShoppingCart.php │ └── User.php └── Providers │ └── AppServiceProvider.php ├── artisan ├── bootstrap ├── app.php ├── cache │ └── .gitignore └── providers.php ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── cache.php ├── database.php ├── devdojo │ └── auth │ │ ├── appearance.php │ │ ├── descriptions.php │ │ ├── language.php │ │ ├── providers.php │ │ └── settings.php ├── filesystems.php ├── logging.php ├── mail.php ├── queue.php ├── services.php └── session.php ├── database ├── .gitignore ├── factories │ └── UserFactory.php ├── migrations │ ├── 0001_01_01_000000_create_users_table.php │ ├── 0001_01_01_000001_create_cache_table.php │ ├── 0001_01_01_000002_create_jobs_table.php │ ├── 2024_04_24_000001_add_user_social_provider_table.php │ ├── 2024_04_24_000002_update_passwords_field_to_be_nullable.php │ ├── 2024_05_07_000003_add_two_factor_auth_columns.php │ ├── 2024_07_25_171025_add_role_column_to_users_table.php │ ├── 2024_07_25_171145_create_categories_table.php │ ├── 2024_07_25_214115_create_products_table.php │ └── 2024_08_01_133930_create_shopping_carts_table.php └── seeders │ └── DatabaseSeeder.php ├── package-lock.json ├── package.json ├── phpunit.xml ├── postcss.config.js ├── public ├── .htaccess ├── auth │ ├── app.css │ ├── build │ │ ├── assets │ │ │ ├── scripts.js │ │ │ └── styles.css │ │ └── manifest.json │ └── img │ │ ├── favicon-dark.png │ │ ├── favicon.ico │ │ └── favicon.png ├── favicon.ico ├── images │ ├── 1.jpg │ └── placeholder-image.jpg ├── index.php └── robots.txt ├── resources ├── css │ └── app.css ├── js │ ├── app.js │ └── bootstrap.js └── views │ ├── admin-layout.blade.php │ ├── components │ ├── categories.blade.php │ ├── layouts │ │ └── app.blade.php │ ├── navigation │ │ └── view-all.blade.php │ └── search-component.blade.php │ ├── errors │ └── 404.blade.php │ ├── livewire │ ├── about-us.blade.php │ ├── add-category.blade.php │ ├── add-product-form.blade.php │ ├── admin-dashboard.blade.php │ ├── all-products.blade.php │ ├── bread-crumb.blade.php │ ├── contacts.blade.php │ ├── edit-product.blade.php │ ├── footer.blade.php │ ├── header.blade.php │ ├── hero-section.blade.php │ ├── item-card.blade.php │ ├── manage-categories.blade.php │ ├── manage-orders.blade.php │ ├── manage-product.blade.php │ ├── product-details.blade.php │ ├── product-listing.blade.php │ ├── product-section.blade.php │ ├── product-table.blade.php │ ├── shopping-cart-component.blade.php │ ├── shopping-cart-icon.blade.php │ ├── skeleton │ │ └── item-skeleton.blade.php │ └── theaders │ │ └── th.blade.php │ └── welcome.blade.php ├── routes ├── console.php └── web.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tailwind.config.js ├── tests ├── Feature │ └── ExampleTest.php ├── TestCase.php └── Unit │ └── ExampleTest.php └── vite.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [docker-compose.yml] 18 | indent_size = 4 19 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_TIMEZONE=UTC 6 | APP_URL=http://localhost 7 | 8 | APP_LOCALE=en 9 | APP_FALLBACK_LOCALE=en 10 | APP_FAKER_LOCALE=en_US 11 | 12 | APP_MAINTENANCE_DRIVER=file 13 | # APP_MAINTENANCE_STORE=database 14 | 15 | BCRYPT_ROUNDS=12 16 | 17 | LOG_CHANNEL=stack 18 | LOG_STACK=single 19 | LOG_DEPRECATIONS_CHANNEL=null 20 | LOG_LEVEL=debug 21 | 22 | DB_CONNECTION=mysql 23 | DB_HOST=127.0.0.1 24 | DB_PORT=3306 25 | DB_DATABASE=minimal_ecommerce_tall_stack 26 | DB_USERNAME=root 27 | DB_PASSWORD= 28 | 29 | SESSION_DRIVER=database 30 | SESSION_LIFETIME=120 31 | SESSION_ENCRYPT=false 32 | SESSION_PATH=/ 33 | SESSION_DOMAIN=null 34 | 35 | BROADCAST_CONNECTION=log 36 | FILESYSTEM_DISK=local 37 | QUEUE_CONNECTION=database 38 | 39 | CACHE_STORE=database 40 | CACHE_PREFIX= 41 | 42 | MEMCACHED_HOST=127.0.0.1 43 | 44 | REDIS_CLIENT=phpredis 45 | REDIS_HOST=127.0.0.1 46 | REDIS_PASSWORD=null 47 | REDIS_PORT=6379 48 | 49 | MAIL_MAILER=log 50 | MAIL_HOST=127.0.0.1 51 | MAIL_PORT=2525 52 | MAIL_USERNAME=null 53 | MAIL_PASSWORD=null 54 | MAIL_ENCRYPTION=null 55 | MAIL_FROM_ADDRESS="hello@example.com" 56 | MAIL_FROM_NAME="${APP_NAME}" 57 | 58 | AWS_ACCESS_KEY_ID= 59 | AWS_SECRET_ACCESS_KEY= 60 | AWS_DEFAULT_REGION=us-east-1 61 | AWS_BUCKET= 62 | AWS_USE_PATH_STYLE_ENDPOINT=false 63 | 64 | VITE_APP_NAME="${APP_NAME}" 65 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.blade.php diff=html 4 | *.css diff=css 5 | *.html diff=html 6 | *.md diff=markdown 7 | *.php diff=php 8 | 9 | /.github export-ignore 10 | CHANGELOG.md export-ignore 11 | .styleci.yml export-ignore 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.phpunit.cache 2 | /node_modules 3 | /public/build 4 | /public/hot 5 | /public/storage 6 | /storage/*.key 7 | /vendor 8 | .env 9 | .env.backup 10 | .env.production 11 | .phpactor.json 12 | .phpunit.result.cache 13 | Homestead.json 14 | Homestead.yaml 15 | auth.json 16 | npm-debug.log 17 | yarn-error.log 18 | /.fleet 19 | /.idea 20 | /.vscode 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | --- 4 | 5 | # Build a Minimal E-commerce App with Laravel 11 and Livewire 3 | TALL Stack 6 | 7 | ## Introduction 8 | Welcome to the Minimal E-commerce App project! This guide will walk you through building a basic e-commerce application using the TALL stack (Tailwind CSS, Alpine.js, Laravel, Livewire). 9 | 10 | ## Features 11 | 12 | - **Setting up the development environment** 13 | - **Designing the landing page with Tailwind CSS & hyper-ui** 14 | - **Creating models, relationships, and migrations for products, categories, and users** 15 | - **Setting up authentication with DevDojo Auth Package** 16 | - **Building the product listing & product detail page** 17 | - **Building the product CRUD operations with Livewire components (admin)** 18 | - **Implementing the shopping cart with Livewire** 19 | - **Order creation by customer** 20 | - **Implementing order management for the admin dashboard** 21 | 22 | ## Implementation Steps 23 | 24 | ### 1. Setting up the Development Environment 25 | - Install Laravel 11 26 | - Configure Livewire 3 27 | - Integrate Tailwind CSS 28 | 29 | ### 2. Setting up Authentication with DevDojo Auth Package 30 | - Install the DevDojo Auth package 31 | - Configure authentication routes and views 32 | 33 | ### 3. Designing the Landing Page with Tailwind CSS & hyper-ui 34 | - Create a responsive landing page 35 | - Use Tailwind CSS for styling 36 | - Utilize hyper-ui components 37 | 38 | ### 4. Building the Product Listing & Product Detail Page 39 | - Create Livewire components for product listing 40 | - Design product detail page 41 | 42 | ### 5. Creating Models, Relationships, and Migrations for Products, Categories, and Users 43 | - Define models and relationships 44 | - Create and run migrations 45 | 46 | ### 6. Building the Product CRUD Operations with Livewire Components (Admin) 47 | - Create Livewire components for CRUD operations 48 | - Implement admin views 49 | 50 | ### 7. Implementing the Shopping Cart with Livewire 51 | - Create a shopping cart component 52 | - Handle adding, updating, and removing items 53 | 54 | 55 | ## Conclusion 56 | This project aims to provide a comprehensive guide for building a minimal e-commerce app using the TALL stack. Each step is designed to be straightforward and provide practical knowledge for developing modern web applications. 57 | 58 | --- 59 | 60 | 61 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | user() && auth()->user()->role == 1) { 19 | return $next($request); 20 | } 21 | 22 | return redirect('/auth/login'); 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Livewire/AboutUs.php: -------------------------------------------------------------------------------- 1 | validate([ 15 | 'category_name' => 'required' 16 | ]); 17 | 18 | $category = new Category(); 19 | $category->name = $this->category_name; 20 | $category->save(); 21 | 22 | return $this->redirect('/manage/categories', navigate: true); 23 | } 24 | public function render() 25 | { 26 | $current_url = url()->current(); 27 | $explode_url = explode('/',$current_url); 28 | 29 | $this->currentUrl = $explode_url[3].' '.$explode_url[4]; 30 | return view('livewire.add-category')->layout('admin-layout'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Livewire/AddProductForm.php: -------------------------------------------------------------------------------- 1 | all_categories = Category::all(); 26 | } 27 | 28 | public function save(){ 29 | $this->validate([ 30 | 'product_name' => 'required', 31 | 'photo' => 'image|required|mimes:jpg,png|max:1024', 32 | 'product_description' => 'required', 33 | 'product_price' => 'required|numeric', 34 | 'category_id' => 'required', 35 | ]); 36 | 37 | $path = $this->photo->store('public/photos'); 38 | 39 | $product = new Product(); 40 | $product->name = $this->product_name; 41 | $product->image = $path; 42 | $product->description = $this->product_description; 43 | $product->price = $this->product_price; 44 | $product->category_id = $this->category_id; 45 | $product->save(); 46 | 47 | return $this->redirect('/products', navigate: true); 48 | } 49 | public function render() 50 | { 51 | $current_url = url()->current(); 52 | $explode_url = explode('/',$current_url); 53 | 54 | $this->currentUrl = $explode_url[3].' '.$explode_url[4]; 55 | 56 | return view('livewire.add-product-form') 57 | ->layout('admin-layout'); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/Livewire/AdminDashboard.php: -------------------------------------------------------------------------------- 1 | current(); 17 | $explode_url = explode('/',$current_url); 18 | 19 | $this->currentUrl = $explode_url[3].' '.$explode_url[4]; 20 | 21 | return view('livewire.admin-dashboard') 22 | ->layout('admin-layout'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Livewire/AllProducts.php: -------------------------------------------------------------------------------- 1 | url = $url; 12 | } 13 | public function render() 14 | { 15 | return view('livewire.bread-crumb'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Livewire/Contacts.php: -------------------------------------------------------------------------------- 1 | title('E-commerce | Contact us'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/Livewire/EditProduct.php: -------------------------------------------------------------------------------- 1 | product_details = Product::find($id); 23 | $this->product_name = $this->product_details->name; 24 | $this->product_description = $this->product_details->description; 25 | $this->product_price = $this->product_details->price; 26 | $this->category_id = $this->product_details->category_id; 27 | $this->photo = $this->product_details->image; 28 | // dd($this->product_details); 29 | $this->all_categories = Category::all(); 30 | } 31 | public function update(){ 32 | //validation 33 | $this->validate([ 34 | 'product_name' => 'required|string|max:255', 35 | 'product_description' => 'required|string', 36 | 'product_price' => 'required|numeric', 37 | 'category_id' => 'required|exists:categories,id', 38 | 'photo' => 'nullable|image|max:1024', // Validate the photo 39 | ]); 40 | //check if the image update/uploaded 41 | if ($this->photo && !is_string($this->photo)) { 42 | $photoPath = $this->photo->store('photos', 'public'); 43 | } else { 44 | $photoPath = $this->photo; // Keep the old image path 45 | } 46 | 47 | $this->product_details->update([ 48 | 'name' => $this->product_name, 49 | 'description' => $this->product_description, 50 | 'price' => $this->product_price, 51 | 'category_id' => $this->category_id, 52 | 'image' => $photoPath, 53 | ]); 54 | 55 | return $this->redirect('/products', navigate: true); 56 | } 57 | public function render() 58 | { 59 | // $current_url = url()->current(); 60 | 61 | // $explode_url = explode('/',$current_url); 62 | // // dd($explode_url); 63 | // $this->currentUrl = $explode_url[3].' '.$explode_url[5]; 64 | 65 | return view('livewire.edit-product')->layout('admin-layout'); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/Livewire/Footer.php: -------------------------------------------------------------------------------- 1 | product = $product_details; 14 | } 15 | public function placeholder(){ 16 | return view('livewire.skeleton.item-skeleton'); 17 | } 18 | 19 | //adding item to cart 20 | public function addToCart($productId) 21 | { 22 | $cartItem = ShoppingCart::where('user_id', Auth::id()) 23 | ->where('product_id', $productId) 24 | ->first(); 25 | 26 | if ($cartItem) { 27 | $cartItem->quantity += 1; // increment its quantity 28 | $cartItem->save(); 29 | } else { 30 | ShoppingCart::create([ 31 | 'user_id' => Auth::id(), 32 | 'product_id' => $productId, 33 | 'quantity' => 1, 34 | ]); 35 | } 36 | //dispatch 37 | $this->dispatch('cartUpdated'); 38 | } 39 | public function render() 40 | { 41 | return view('livewire.item-card'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Livewire/ManageCategories.php: -------------------------------------------------------------------------------- 1 | sortBy == $sortColum) { 21 | $this->sortDir = ($this->sortDir == 'ASC') ? 'DESC' : 'ASC'; 22 | return; 23 | } 24 | 25 | $this->sortBy = $sortColum; 26 | $this->sortDir = 'ASC'; 27 | } 28 | public function render() 29 | { 30 | $current_url = url()->current(); 31 | $explode_url = explode('/',$current_url); 32 | 33 | $this->currentUrl = $explode_url[3].' '.$explode_url[4]; 34 | 35 | return view('livewire.manage-categories',[ 36 | 'categories' => Category::search($this->search) 37 | ->orderBy($this->sortBy,$this->sortDir) 38 | ->paginate($this->perPage) 39 | ]) 40 | ->layout('admin-layout'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/Livewire/ManageOrders.php: -------------------------------------------------------------------------------- 1 | layout('admin-layout'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/Livewire/ManageProduct.php: -------------------------------------------------------------------------------- 1 | layout('admin-layout'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Livewire/ProductDetails.php: -------------------------------------------------------------------------------- 1 | product = Product::find($product_id); 15 | } 16 | 17 | //adding item to cart 18 | public function addToCart($productId) 19 | { 20 | $cartItem = ShoppingCart::where('user_id', Auth::id()) 21 | ->where('product_id', $productId) 22 | ->first(); 23 | 24 | if ($cartItem) { 25 | $cartItem->quantity += 1; // increment its quantity 26 | $cartItem->save(); 27 | } else { 28 | ShoppingCart::create([ 29 | 'user_id' => Auth::id(), 30 | 'product_id' => $productId, 31 | 'quantity' => 1, 32 | ]); 33 | } 34 | //dispatch 35 | $this->dispatch('cartUpdated'); 36 | } 37 | public function render() 38 | { 39 | return view('livewire.product-details'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Livewire/ProductListing.php: -------------------------------------------------------------------------------- 1 | category_id = $category_id; 19 | $this->current_product_id = $current_product_id; 20 | $this->updateProductList(); 21 | } 22 | 23 | public function updatedSearchTerm() 24 | { 25 | $this->updateProductList(); 26 | } 27 | 28 | public function updateProductList() 29 | { 30 | if ($this->category_id == 0) { 31 | $this->products = Product::with('category') 32 | ->where('id', '!=', $this->current_product_id) 33 | ->where('name', 'like', '%' . $this->searchTerm . '%') 34 | ->orderBy('created_at', 'DESC') 35 | ->limit(4) 36 | ->get(); 37 | } elseif ($this->category_id == 'all') { 38 | $this->products = Product::with('category') 39 | ->where('name', 'like', '%' . $this->searchTerm . '%') 40 | ->get(); 41 | } else { 42 | $this->products = Product::with('category') 43 | ->where('category_id', $this->category_id) 44 | ->where('id', '!=', $this->current_product_id) 45 | ->where('name', 'like', '%' . $this->searchTerm . '%') 46 | ->limit(4) 47 | ->get(); 48 | } 49 | } 50 | 51 | public function render() 52 | { 53 | return view('livewire.product-listing', [ 54 | 'categories' => Category::all() 55 | ]); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /app/Livewire/ProductSection.php: -------------------------------------------------------------------------------- 1 | sortBy == $sortColum) { 22 | $this->sortDir = ($this->sortDir == 'ASC') ? 'DESC' : 'ASC'; 23 | return; 24 | } 25 | 26 | $this->sortBy = $sortColum; 27 | $this->sortDir = 'ASC'; 28 | } 29 | 30 | public function delete($id){ 31 | $product = Product::find($id); 32 | 33 | $product->delete(); 34 | 35 | return $this->redirect('/products', navigate: true); 36 | } 37 | public function render() 38 | { 39 | $current_url = url()->current(); 40 | $explode_url = explode('/',$current_url); 41 | 42 | $this->currentUrl = $explode_url[3]; 43 | 44 | return view('livewire.product-table',[ 45 | 'products' => Product::with('category')->search($this->search) 46 | ->orderBy($this->sortBy,$this->sortDir) 47 | ->paginate($this->perPage) 48 | ]); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Livewire/ShoppingCartComponent.php: -------------------------------------------------------------------------------- 1 | 'render', 21 | ]; 22 | public function mount(){ 23 | $this->cartItems = $this->getCartItems(); 24 | $this->calculateTotals(); 25 | } 26 | 27 | //calculate the totals 28 | public function calculateTotals() 29 | { 30 | $this->subtotal = $this->cartItems->sum(function($item) { 31 | return $item->quantity * $item->product->price; 32 | }); 33 | $this->vat = $this->subtotal * 0.1; // 10% VAT example 34 | $this->discount = 5; // Apply your discount logic here 35 | $this->total = $this->subtotal + $this->vat - $this->discount; 36 | } 37 | 38 | //get the details of shopping cart 39 | public function getCartItems() 40 | { 41 | return ShoppingCart::with('product') 42 | ->where('user_id', Auth::id()) 43 | ->get(); 44 | } 45 | //adding item to cart 46 | public function addToCart($productId) 47 | { 48 | $cartItem = ShoppingCart::where('user_id', Auth::id()) 49 | ->where('product_id', $productId) 50 | ->first(); 51 | 52 | if ($cartItem) { 53 | $cartItem->quantity += 1; // increment its quantity 54 | $cartItem->save(); 55 | } else { 56 | ShoppingCart::create([ 57 | 'user_id' => Auth::id(), 58 | 'product_id' => $productId, 59 | 'quantity' => 1, 60 | ]); 61 | } 62 | //dispatch 63 | $this->dispatch('cartUpdated'); 64 | } 65 | 66 | //update cart function 67 | public function updateQuantity($cartItemId, $quantity) 68 | { 69 | $cartItem = ShoppingCart::find($cartItemId); 70 | if ($cartItem) { 71 | $cartItem->quantity = $quantity; 72 | $cartItem->save(); 73 | $this->dispatch('cartUpdated'); 74 | } 75 | } 76 | 77 | //remove items from the cart 78 | public function removeItem($cartItemId) 79 | { 80 | $cartItem = ShoppingCart::find($cartItemId); 81 | if ($cartItem) { 82 | $cartItem->delete(); 83 | $this->dispatch('cartUpdated'); 84 | } 85 | } 86 | public function render() 87 | { 88 | $this->cartItems = $this->getCartItems(); 89 | $this->calculateTotals(); 90 | 91 | return view('livewire.shopping-cart-component', [ 92 | 'cartItems' => $this->cartItems 93 | ])->title('E-commerce | Shopping cart'); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/Livewire/ShoppingCartIcon.php: -------------------------------------------------------------------------------- 1 | 'updateCartCount', 15 | ]; 16 | 17 | public function mount(){ 18 | $this->updateCartCount(); 19 | } 20 | 21 | public function updateCartCount(){ 22 | //get the count from shopping cart table.. 23 | $this->cartCount = ShoppingCart::where('user_id', Auth::id())->sum('quantity'); 24 | } 25 | public function render() 26 | { 27 | return view('livewire.shopping-cart-icon'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Models/Category.php: -------------------------------------------------------------------------------- 1 | hasMany(Product::class); 17 | } 18 | 19 | public function scopeSearch($query, $value){ 20 | $query->where('name','like',"%{$value}%"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Models/Product.php: -------------------------------------------------------------------------------- 1 | belongsTo(Category::class); 17 | } 18 | 19 | public function scopeSearch($query, $value){ 20 | $query->where('name','like',"%{$value}%") 21 | ->orWhere('description','like',"%{$value}%"); 22 | } 23 | } -------------------------------------------------------------------------------- /app/Models/ShoppingCart.php: -------------------------------------------------------------------------------- 1 | belongsTo(User::class); 22 | } 23 | 24 | public function product() 25 | { 26 | return $this->belongsTo(Product::class); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Models/User.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | protected $fillable = [ 20 | 'name', 21 | 'email', 22 | 'password', 23 | 'role', 24 | ]; 25 | 26 | /** 27 | * The attributes that should be hidden for serialization. 28 | * 29 | * @var arrayOops, something went wrong.
26 |Sorry, we couldn't find your page.
27 |12 | Besides working with start-up enterprises as a partner for digitalization, we have built enterprise products for common pain points that we have encountered in various products and projects. 13 |
14 |27 | We choose our teams carefully. Our people are the secret to great work. 28 |
29 |41 | From boarding passes to movie tickets, there's pretty much nothing you can't store with Preline. 42 |
43 |55 | Our documentation and extensive Client libraries contain everything a business needs to build a custom integration. 56 |
57 |69 | We actively pursue the right balance between functionality and aesthetics, creating delightful experiences. 70 |
71 |9 | Tell us your story and we’ll be in touch. 10 |
11 |10 | Browse our collection of high-quality products and enjoy seamless online shopping. 11 |
12 | 13 |
5 | 17 | Add category, edit and more. 18 |
19 || 49 | | 50 | | |||
|---|---|---|---|---|
|
58 |
59 |
64 |
60 | {{str($category->name)->words(3)}}
61 |
62 |
63 | |
65 |
66 |
67 | {{ date('D M Y, H:i',strtotime($category->created_at))}}
68 |
69 | |
70 |
71 |
72 |
73 | Edit
74 |
75 |
76 | |
77 |
78 |
79 |
80 | Delete
81 |
82 |
83 | |
84 | |
|
89 |
90 |
91 | No Data Found!
92 |
93 |
94 | |
95 | ||||
4 | 17 | Add Product, edit and more. 18 |
19 || 64 | | 65 | | |||||
|---|---|---|---|---|---|---|
| 73 | 85 | | 86 |
87 |
88 | {{ str($product->description)->words(8)}}
89 |
90 | |
91 |
92 |
93 |
94 | ${{$product->price}}
95 |
96 |
97 | |
98 |
99 |
100 |
101 | {{$product->category->name}}
102 |
103 |
104 | |
105 |
106 |
107 | {{ date('D M Y, H:i',strtotime($product->created_at))}}
108 |
109 | |
110 |
111 |
112 |
113 | Edit
114 |
115 |
116 | |
117 |
118 |
119 |
120 | Delete
121 |
122 |
123 | |
124 |
|
129 |
130 |
131 | No Data Found!
132 |
133 |
134 | |
135 | ||||||
1 Discounts Applied
75 | 76 |