├── hooks
└── hooks.json
├── public
├── favicon.ico
├── robots.txt
├── storage
├── images
│ ├── cover.jpg
│ ├── not-found.jpg
│ ├── users
│ │ └── default.png
│ └── products
│ │ └── dummy
│ │ ├── image0.jpg
│ │ ├── image1.jpg
│ │ ├── image2.jpg
│ │ ├── image3.jpg
│ │ ├── image4.jpg
│ │ └── image5.jpg
├── mix-manifest.json
├── fonts
│ └── vendor
│ │ └── font-awesome
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ └── fontawesome-webfont.woff2
├── .htaccess
└── index.php
├── bootstrap
├── cache
│ └── .gitignore
└── app.php
├── storage
├── logs
│ └── .gitignore
├── debugbar
│ └── .gitignore
├── framework
│ ├── sessions
│ │ └── .gitignore
│ ├── testing
│ │ └── .gitignore
│ ├── views
│ │ └── .gitignore
│ ├── cache
│ │ ├── data
│ │ │ └── .gitignore
│ │ └── .gitignore
│ └── .gitignore
└── app
│ ├── .gitignore
│ └── public
│ ├── users
│ └── default.png
│ └── products
│ ├── dummy
│ ├── image0.jpg
│ ├── image1.jpg
│ ├── image2.jpg
│ ├── image3.jpg
│ ├── image4.jpg
│ └── image5.jpg
│ └── September2020
│ ├── 7bmQiRD5DOS6QZTrprlb.jpg
│ ├── DKCbwzXCrbgRjlUJjlko.jpg
│ ├── FHyZzRWZ0Ze0CAqiURkx.jpg
│ ├── gMuKbTUCz2AW9OS2Gqv1.jpg
│ ├── nx65t4W6tw17XFoPnfrb.jpg
│ └── xWLnSwcwkH4r7yhDn00F.jpg
├── Procfile
├── database
├── .gitignore
├── seeds
│ ├── MenusTableSeeder.php
│ ├── MenusTableSeederCustom.php
│ ├── TagsTableSeeder.php
│ ├── ProductTagSeeder.php
│ ├── DatabaseSeeder.php
│ ├── VoyagerDummyDatabaseSeeder.php
│ ├── PermissionRoleTableSeeder.php
│ ├── CouponsTableSeeder.php
│ ├── OrderProductTableSeeder.php
│ ├── PermissionRoleTableSeederCustom.php
│ ├── RolesTableSeeder.php
│ ├── VoyagerDatabaseSeeder.php
│ ├── VoyagerDatabaseSeederCustom.php
│ ├── UsersTableSeeder.php
│ ├── PermissionsTableSeeder.php
│ ├── CategoryTableSeeder.php
│ ├── SettingsTableSeederCustom.php
│ ├── PermissionsTableSeederCustom.php
│ ├── OrdersTableSeeder.php
│ └── DataTypesTableSeeder.php
├── migrations
│ ├── 2014_10_12_100000_create_password_resets_table.php
│ ├── 2019_10_19_145706_add_images_column_to_products.php
│ ├── 2019_10_20_114921_create_tags_table.php
│ ├── 2019_10_17_195112_create_categories_table.php
│ ├── 2019_11_09_002942_add_quantity_to_products_table.php
│ ├── 2020_06_27_012504_create_visits_table.php
│ ├── 2019_08_19_000000_create_failed_jobs_table.php
│ ├── 2019_10_18_002421_create_coupons_table.php
│ ├── 2019_10_16_185424_create_products_table.php
│ ├── 2019_10_20_115306_create_products_tags_table.php
│ ├── 2014_10_12_000000_create_users_table.php
│ ├── 2019_10_17_195227_add_category_id_to_products_table.php
│ ├── 2019_10_22_190613_create_order_product_table.php
│ └── 2019_10_22_185425_create_orders_table.php
└── factories
│ └── UserFactory.php
├── config
├── hooks.php
├── voyager-hooks.php
├── image.php
├── view.php
├── services.php
├── hashing.php
├── broadcasting.php
├── cart.php
├── filesystems.php
├── queue.php
├── logging.php
├── scout.php
├── cache.php
└── auth.php
├── resources
├── sass
│ ├── cover.jpg
│ ├── _checkout.scss
│ ├── _cart.scss
│ ├── _variables.scss
│ ├── app.scss
│ ├── _product.scss
│ ├── _welcome.scss
│ ├── _shop.scss
│ └── _main.scss
├── views
│ ├── errors
│ │ ├── 404.blade.php
│ │ ├── 401.blade.php
│ │ ├── 419.blade.php
│ │ ├── 429.blade.php
│ │ ├── 500.blade.php
│ │ ├── 403.blade.php
│ │ ├── 503.blade.php
│ │ ├── layout.blade.php
│ │ └── minimal.blade.php
│ ├── partials
│ │ ├── errors.blade.php
│ │ ├── session.blade.php
│ │ ├── head.blade.php
│ │ ├── menu
│ │ │ └── main.blade.php
│ │ ├── footer.blade.php
│ │ ├── might-like.blade.php
│ │ └── nav.blade.php
│ ├── emails
│ │ └── orders
│ │ │ └── placed.blade.php
│ ├── layouts
│ │ └── app.blade.php
│ ├── home.blade.php
│ ├── auth
│ │ ├── verify.blade.php
│ │ ├── passwords
│ │ │ ├── email.blade.php
│ │ │ └── reset.blade.php
│ │ ├── register.blade.php
│ │ └── login.blade.php
│ ├── search.blade.php
│ ├── product.blade.php
│ ├── admin
│ │ └── visits.blade.php
│ ├── shop.blade.php
│ └── welcome.blade.php
├── js
│ ├── bootstrap.js
│ ├── components
│ │ └── ExampleComponent.vue
│ ├── main.js
│ └── app.js
└── lang
│ └── en
│ ├── pagination.php
│ ├── auth.php
│ └── passwords.php
├── .gitattributes
├── .vscode
└── settings.json
├── .gitignore
├── tests
├── TestCase.php
├── Unit
│ └── ExampleTest.php
├── Feature
│ └── ExampleTest.php
└── CreatesApplication.php
├── app
├── Tag.php
├── ProductTag.php
├── OrderProduct.php
├── Category.php
├── CountryVisit.php
├── Http
│ ├── Middleware
│ │ ├── EncryptCookies.php
│ │ ├── CheckForMaintenanceMode.php
│ │ ├── TrimStrings.php
│ │ ├── TrustProxies.php
│ │ ├── Authenticate.php
│ │ ├── VerifyCsrfToken.php
│ │ ├── AdminMiddleware.php
│ │ ├── RedirectIfAuthenticated.php
│ │ └── VisitsMiddleware.php
│ ├── Controllers
│ │ ├── Controller.php
│ │ ├── WelcomePageController.php
│ │ ├── HomeController.php
│ │ ├── VisitsController.php
│ │ ├── Auth
│ │ │ ├── ForgotPasswordController.php
│ │ │ ├── ResetPasswordController.php
│ │ │ ├── ConfirmPasswordController.php
│ │ │ ├── VerificationController.php
│ │ │ ├── RegisterController.php
│ │ │ └── LoginController.php
│ │ ├── CouponsController.php
│ │ ├── ShopController.php
│ │ ├── Voyager
│ │ │ └── OrdersController.php
│ │ └── CartController.php
│ ├── Requests
│ │ └── CheckoutRequest.php
│ └── Kernel.php
├── Providers
│ ├── BroadcastServiceProvider.php
│ ├── AppServiceProvider.php
│ ├── AuthServiceProvider.php
│ ├── EventServiceProvider.php
│ └── RouteServiceProvider.php
├── Coupon.php
├── Mail
│ └── OrderPlaced.php
├── Order.php
├── library
│ └── helper.php
├── Console
│ ├── Kernel.php
│ └── Commands
│ │ ├── EcommerceInstall.php
│ │ └── HerokuSetup.php
├── User.php
├── Product.php
└── Exceptions
│ └── Handler.php
├── .editorconfig
├── .styleci.yml
├── routes
├── channels.php
├── api.php
├── console.php
└── web.php
├── webpack.mix.js
├── server.php
├── .example.env
├── LICENSE
├── phpunit.xml
├── package.json
├── artisan
├── README.md
└── composer.json
/hooks/hooks.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/bootstrap/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/logs/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: vendor/bin/heroku-php-apache2 public/
--------------------------------------------------------------------------------
/database/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite
2 | *.sqlite-journal
3 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/public/storage:
--------------------------------------------------------------------------------
1 | /var/www/ecommerce/storage/app/public
--------------------------------------------------------------------------------
/storage/debugbar/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/sessions/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/storage/framework/testing/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/views/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/cache/data/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !data/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/storage/app/.gitignore:
--------------------------------------------------------------------------------
1 | public/products/September
2 | !.gitignore
3 | backup
--------------------------------------------------------------------------------
/config/hooks.php:
--------------------------------------------------------------------------------
1 | env('HOOKS_ENABLED', true),
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/public/images/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/cover.jpg
--------------------------------------------------------------------------------
/public/mix-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "/js/app.js": "/js/app.js",
3 | "/css/app.css": "/css/app.css"
4 | }
5 |
--------------------------------------------------------------------------------
/resources/sass/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/resources/sass/cover.jpg
--------------------------------------------------------------------------------
/public/images/not-found.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/not-found.jpg
--------------------------------------------------------------------------------
/public/images/users/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/users/default.png
--------------------------------------------------------------------------------
/storage/app/public/users/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/users/default.png
--------------------------------------------------------------------------------
/public/images/products/dummy/image0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/products/dummy/image0.jpg
--------------------------------------------------------------------------------
/public/images/products/dummy/image1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/products/dummy/image1.jpg
--------------------------------------------------------------------------------
/public/images/products/dummy/image2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/products/dummy/image2.jpg
--------------------------------------------------------------------------------
/public/images/products/dummy/image3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/products/dummy/image3.jpg
--------------------------------------------------------------------------------
/public/images/products/dummy/image4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/products/dummy/image4.jpg
--------------------------------------------------------------------------------
/public/images/products/dummy/image5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/images/products/dummy/image5.jpg
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.css linguist-vendored
3 | *.scss linguist-vendored
4 | *.js linguist-vendored
5 | CHANGELOG.md export-ignore
6 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "Aloglia"
4 | ],
5 | "cSpell.ignoreWords": [
6 | "aloglia"
7 | ]
8 | }
--------------------------------------------------------------------------------
/storage/app/public/products/dummy/image0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/dummy/image0.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/dummy/image1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/dummy/image1.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/dummy/image2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/dummy/image2.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/dummy/image3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/dummy/image3.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/dummy/image4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/dummy/image4.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/dummy/image5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/dummy/image5.jpg
--------------------------------------------------------------------------------
/storage/framework/.gitignore:
--------------------------------------------------------------------------------
1 | config.php
2 | routes.php
3 | schedule-*
4 | compiled.php
5 | services.json
6 | events.scanned.php
7 | routes.scanned.php
8 | down
9 |
--------------------------------------------------------------------------------
/public/fonts/vendor/font-awesome/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/fonts/vendor/font-awesome/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/public/fonts/vendor/font-awesome/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/fonts/vendor/font-awesome/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/public/fonts/vendor/font-awesome/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/fonts/vendor/font-awesome/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/vendor/font-awesome/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/public/fonts/vendor/font-awesome/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/resources/views/errors/404.blade.php:
--------------------------------------------------------------------------------
1 | @extends('errors::minimal')
2 |
3 | @section('title', __('Not Found'))
4 | @section('code', '404')
5 | @section('message', __('Not Found'))
6 |
--------------------------------------------------------------------------------
/resources/sass/_checkout.scss:
--------------------------------------------------------------------------------
1 | .coupon {
2 | border: 1px solid #222;
3 | padding: 1em;
4 | }
5 |
6 | .quantity-square {
7 | border: 1px solid #222;
8 | padding: 0.5em;
9 | }
--------------------------------------------------------------------------------
/resources/views/errors/401.blade.php:
--------------------------------------------------------------------------------
1 | @extends('errors::minimal')
2 |
3 | @section('title', __('Unauthorized'))
4 | @section('code', '401')
5 | @section('message', __('Unauthorized'))
6 |
--------------------------------------------------------------------------------
/resources/views/errors/419.blade.php:
--------------------------------------------------------------------------------
1 | @extends('errors::minimal')
2 |
3 | @section('title', __('Page Expired'))
4 | @section('code', '419')
5 | @section('message', __('Page Expired'))
6 |
--------------------------------------------------------------------------------
/resources/views/errors/429.blade.php:
--------------------------------------------------------------------------------
1 | @extends('errors::minimal')
2 |
3 | @section('title', __('Too Many Requests'))
4 | @section('code', '429')
5 | @section('message', __('Too Many Requests'))
6 |
--------------------------------------------------------------------------------
/storage/app/public/products/September2020/7bmQiRD5DOS6QZTrprlb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/September2020/7bmQiRD5DOS6QZTrprlb.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/September2020/DKCbwzXCrbgRjlUJjlko.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/September2020/DKCbwzXCrbgRjlUJjlko.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/September2020/FHyZzRWZ0Ze0CAqiURkx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/September2020/FHyZzRWZ0Ze0CAqiURkx.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/September2020/gMuKbTUCz2AW9OS2Gqv1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/September2020/gMuKbTUCz2AW9OS2Gqv1.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/September2020/nx65t4W6tw17XFoPnfrb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/September2020/nx65t4W6tw17XFoPnfrb.jpg
--------------------------------------------------------------------------------
/storage/app/public/products/September2020/xWLnSwcwkH4r7yhDn00F.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crypto27dev/eCommerce_laravel/HEAD/storage/app/public/products/September2020/xWLnSwcwkH4r7yhDn00F.jpg
--------------------------------------------------------------------------------
/resources/views/errors/500.blade.php:
--------------------------------------------------------------------------------
1 | @extends('errors::minimal')
2 |
3 | @section('title', __('Service not available'))
4 | @section('message', __('Sorry, This demo site is unavailable right now.'))
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /public/hot
3 | /storage/*.key
4 | /vendor
5 | .env
6 | .env.backup
7 | .phpunit.result.cache
8 | Homestead.json
9 | Homestead.yaml
10 | npm-debug.log
11 | yarn-error.log
12 |
--------------------------------------------------------------------------------
/resources/views/errors/403.blade.php:
--------------------------------------------------------------------------------
1 | @extends('errors::minimal')
2 |
3 | @section('title', __('Forbidden'))
4 | @section('code', '403')
5 | @section('message', __($exception->getMessage() ?: 'Forbidden'))
6 |
--------------------------------------------------------------------------------
/resources/views/partials/errors.blade.php:
--------------------------------------------------------------------------------
1 | @if(count($errors) > 0)
2 | @foreach($errors->all() as $error)
3 |
4 |
{!! $error !!}
5 |
6 | @endforeach
7 | @endif
--------------------------------------------------------------------------------
/resources/views/errors/503.blade.php:
--------------------------------------------------------------------------------
1 | @extends('errors::minimal')
2 |
3 | @section('title', __('Service Unavailable'))
4 | @section('code', '503')
5 | @section('message', __($exception->getMessage() ?: 'Service Unavailable'))
6 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | belongsToMany('App\Product');
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/ProductTag.php:
--------------------------------------------------------------------------------
1 | env('HOOKS_ENABLED', true),
6 |
7 | 'add-route' => true,
8 | 'add-hook-menu-item' => true,
9 | 'add-hook-permissions' => true,
10 | 'publish-vendor-files' => true,
11 |
12 | ];
13 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | indent_style = space
8 | indent_size = 4
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
14 | [*.{yml,yaml}]
15 | indent_size = 2
16 |
--------------------------------------------------------------------------------
/app/Category.php:
--------------------------------------------------------------------------------
1 | hasMany('App\Product');
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | php:
2 | preset: laravel
3 | enabled:
4 | - alpha_ordered_imports
5 | disabled:
6 | - length_ordered_imports
7 | - unused_use
8 | finder:
9 | not-name:
10 | - index.php
11 | - server.php
12 | js:
13 | finder:
14 | not-name:
15 | - webpack.mix.js
16 | css: true
17 |
--------------------------------------------------------------------------------
/resources/sass/_cart.scss:
--------------------------------------------------------------------------------
1 | .summary {
2 | padding: 1em;
3 | background-color: #ddd;
4 | }
5 |
6 | .inline-form-button {
7 | padding: 0;
8 | margin: 0;
9 | border: 0;
10 | background-color: #eee;
11 | font-size: 13px;
12 | color: #444;
13 | }
14 |
15 | .cart-option {
16 | margin: 0;
17 | }
--------------------------------------------------------------------------------
/app/CountryVisit.php:
--------------------------------------------------------------------------------
1 | increment('visits');
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/resources/views/partials/session.blade.php:
--------------------------------------------------------------------------------
1 | @if (session()->has('success'))
2 |
3 |
{{ session()->get('success') }}
4 |
5 | @endif
6 |
7 | @if (session()->has('error'))
8 |
9 |
{{ session()->get('error') }}
10 |
11 | @endif
--------------------------------------------------------------------------------
/app/Http/Middleware/EncryptCookies.php:
--------------------------------------------------------------------------------
1 | assertTrue(true);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/resources/sass/_variables.scss:
--------------------------------------------------------------------------------
1 | // Body
2 | $body-bg: #f8fafc;
3 |
4 | // Typography
5 | $font-family-sans-serif: 'Nunito', sans-serif;
6 | $font-size-base: 0.9rem;
7 | $line-height-base: 1.6;
8 |
9 | // Colors
10 | $blue: #3490dc;
11 | $indigo: #6574cd;
12 | $purple: #9561e2;
13 | $pink: #f66d9b;
14 | $red: #e3342f;
15 | $orange: #f6993f;
16 | $yellow: #ffed4a;
17 | $green: #38c172;
18 | $teal: #4dc0b5;
19 | $cyan: #6cb2eb;
20 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Controller.php:
--------------------------------------------------------------------------------
1 | 'admin',
19 | ]);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/Feature/ExampleTest.php:
--------------------------------------------------------------------------------
1 | get('/');
18 |
19 | $response->assertStatus(200);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/database/seeds/MenusTableSeederCustom.php:
--------------------------------------------------------------------------------
1 | 'main',
19 | ]);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/CreatesApplication.php:
--------------------------------------------------------------------------------
1 | make(Kernel::class)->bootstrap();
19 |
20 | return $app;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Providers/BroadcastServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'Tag ' . $i,
20 | 'slug' => 'tag-' . $i
21 | ]);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/resources/sass/_product.scss:
--------------------------------------------------------------------------------
1 |
2 | .product-image {
3 | padding: 0;
4 | }
5 |
6 | .image-thumbnails {
7 | display: grid;
8 | grid-template-columns: repeat(4, 1fr);
9 | grid-gap: 8px;
10 | margin-top: 13px;
11 |
12 | .active {
13 | border: 2px solid black;
14 | }
15 | }
16 |
17 | .image-thumbnail {
18 | width: 100%;
19 | height: 100%;
20 | overflow: hidden;
21 | border: 2px solid lightgray;
22 |
23 | &:hover {
24 | border: 2px solid #000;
25 | cursor: pointer;
26 | }
27 | }
--------------------------------------------------------------------------------
/app/Http/Controllers/WelcomePageController.php:
--------------------------------------------------------------------------------
1 | take(6)->get();
13 | $hotProducts = Product::inRandomOrder()->take(3)->get();
14 | return view('welcome')->with([
15 | 'products'=> $products,
16 | 'hotProducts' => $hotProducts
17 | ]);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/Providers/AppServiceProvider.php:
--------------------------------------------------------------------------------
1 | rand(1, 120),
20 | 'tag_id' => rand(1, 4)
21 | ]);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/Http/Middleware/TrustProxies.php:
--------------------------------------------------------------------------------
1 | first();
12 | }
13 |
14 | public function discount($total) {
15 | if($this->type == 'fixed') {
16 | return $this->value;
17 | } else if($this->type == 'percent') {
18 | return ($this->percent_off / 100) * $total;
19 | } else {
20 | return 0;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/Http/Middleware/Authenticate.php:
--------------------------------------------------------------------------------
1 | expectsJson()) {
18 | return route('login');
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/routes/channels.php:
--------------------------------------------------------------------------------
1 | id === (int) $id;
16 | });
17 |
--------------------------------------------------------------------------------
/database/seeds/DatabaseSeeder.php:
--------------------------------------------------------------------------------
1 | call(CategoryTableSeeder::class);
17 | $this->call(TagsTableSeeder::class);
18 | $this->call(CouponsTableSeeder::class);
19 | $this->call(ProductsTableSeeder::class);
20 | $this->call(ProductTagSeeder::class);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Http/Middleware/VerifyCsrfToken.php:
--------------------------------------------------------------------------------
1 | Order:
5 | mail : {{ $order->billing_email }}
6 | Name : {{ $order->billing_name }}
7 | Total : {{ $order->billing_total }}
8 | products:
9 | @foreach ($order->products as $product)
10 | {{ $product->name }} : {{ $product->pivot->quantity }}
11 | @endforeach
12 |
13 | @component('mail::button', ['url' => config('app.url')])
14 | Go To The Site
15 | @endcomponent
16 |
17 | Thanks,
18 | {{ config('app.name') }}
19 | @endcomponent
20 |
--------------------------------------------------------------------------------
/config/image.php:
--------------------------------------------------------------------------------
1 | 'gd'
19 |
20 | ];
21 |
--------------------------------------------------------------------------------
/webpack.mix.js:
--------------------------------------------------------------------------------
1 | const mix = require('laravel-mix');
2 |
3 | /*
4 | |--------------------------------------------------------------------------
5 | | Mix Asset Management
6 | |--------------------------------------------------------------------------
7 | |
8 | | Mix provides a clean, fluent API for defining some Webpack build steps
9 | | for your Laravel application. By default, we are compiling the Sass
10 | | file for the application as well as bundling up all the JS files.
11 | |
12 | */
13 |
14 | mix.js('resources/js/app.js', 'public/js')
15 | .sass('resources/sass/app.scss', 'public/css');
16 |
--------------------------------------------------------------------------------
/routes/api.php:
--------------------------------------------------------------------------------
1 | get('/user', function (Request $request) {
17 | return $request->user();
18 | });
19 |
--------------------------------------------------------------------------------
/database/seeds/VoyagerDummyDatabaseSeeder.php:
--------------------------------------------------------------------------------
1 | seedersPath = database_path('seeds').'/';
22 | $this->call(UsersTableSeeder::class);
23 | $this->call(PermissionRoleTableSeeder::class);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/Http/Controllers/HomeController.php:
--------------------------------------------------------------------------------
1 | middleware('auth');
17 | }
18 |
19 | /**
20 | * Show the application dashboard.
21 | *
22 | * @return \Illuminate\Contracts\Support\Renderable
23 | */
24 | public function index()
25 | {
26 | return view('home');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/Http/Middleware/AdminMiddleware.php:
--------------------------------------------------------------------------------
1 | check() || !auth()->user()->role->name == 'admin') {
19 | abort(403, 'Sorry, You don\'t have permission to access this page');
20 | }
21 | return $next($request);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/resources/lang/en/pagination.php:
--------------------------------------------------------------------------------
1 | '« Previous',
17 | 'next' => 'Next »',
18 |
19 | ];
20 |
--------------------------------------------------------------------------------
/routes/console.php:
--------------------------------------------------------------------------------
1 | comment(Inspiring::quote());
18 | })->describe('Display an inspiring quote');
19 |
--------------------------------------------------------------------------------
/resources/sass/_welcome.scss:
--------------------------------------------------------------------------------
1 | .hero-image {
2 | background-image: url("cover.jpg");
3 | display: flex;
4 | flex-direction: column;
5 | min-height: 28em;
6 | height: 50%;
7 | align-self: center;
8 | background-repeat: no-repeat;
9 | background-size: cover;
10 | background-attachment: scroll;
11 | /* justify-content: center; */
12 | margin-bottom: 2em;
13 | }
14 |
15 | .hero-content {
16 | overflow: visible;
17 | margin-left: 2em;
18 | margin-top:4em;
19 | color: white;
20 | }
21 |
22 | .show-more {
23 | display: flex;
24 | align-items: center;
25 | justify-content: center;
26 | }
--------------------------------------------------------------------------------
/resources/views/layouts/app.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | @include('partials.head')
4 |
9 |
10 |
11 | @include('partials.nav')
12 |
13 | @include('partials.session')
14 | @include('partials.errors')
15 | @yield('content')
16 |
17 | @include('partials.footer')
18 |
19 |
20 | @yield('scripts')
21 |
22 |
--------------------------------------------------------------------------------
/database/seeds/PermissionRoleTableSeeder.php:
--------------------------------------------------------------------------------
1 | firstOrFail();
19 |
20 | $permissions = Permission::all();
21 |
22 | $role->permissions()->sync(
23 | $permissions->pluck('id')->all()
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/Http/Controllers/VisitsController.php:
--------------------------------------------------------------------------------
1 | limit(10)
13 | ->select('country', 'visits')->get();
14 |
15 | $CountryVisit = CountryVisit::orderBy('visits', 'desc')->paginate(10);
16 | return view('admin.visits')->with([
17 | 'CountryVisit' => $CountryVisit,
18 | 'topCountries' => $topCountries,
19 | ]);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/database/seeds/CouponsTableSeeder.php:
--------------------------------------------------------------------------------
1 | 'ABC123',
19 | 'type' => 'fixed',
20 | 'value' => 20,
21 | ]);
22 | Coupon::create([
23 | 'code' => 'DEF456',
24 | 'type' => 'percent',
25 | 'percent_off' => 40,
26 | ]);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/database/seeds/OrderProductTableSeeder.php:
--------------------------------------------------------------------------------
1 | rand(1, 120),
21 | 'order_id' => Order::all()->random()->id,
22 | 'quantity' => rand(1,3),
23 | ]);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/database/seeds/PermissionRoleTableSeederCustom.php:
--------------------------------------------------------------------------------
1 | firstOrFail();
19 |
20 | $permissions = Permission::all();
21 |
22 | $role->permissions()->sync(
23 | $permissions->pluck('id')->all()
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/server.php:
--------------------------------------------------------------------------------
1 |
8 | */
9 |
10 | $uri = urldecode(
11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
12 | );
13 |
14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the
15 | // built-in PHP web server. This provides a convenient way to test a Laravel
16 | // application without having installed a "real" web server software here.
17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {
18 | return false;
19 | }
20 |
21 | require_once __DIR__.'/public/index.php';
22 |
--------------------------------------------------------------------------------
/app/Http/Middleware/RedirectIfAuthenticated.php:
--------------------------------------------------------------------------------
1 | check()) {
21 | return redirect('/');
22 | }
23 |
24 | return $next($request);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/resources/js/components/ExampleComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | I'm an example component.
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
24 |
--------------------------------------------------------------------------------
/public/.htaccess:
--------------------------------------------------------------------------------
1 |
2 |
3 | Options -MultiViews -Indexes
4 |
5 |
6 | RewriteEngine On
7 |
8 | # Handle Authorization Header
9 | RewriteCond %{HTTP:Authorization} .
10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
11 |
12 | # Redirect Trailing Slashes If Not A Folder...
13 | RewriteCond %{REQUEST_FILENAME} !-d
14 | RewriteCond %{REQUEST_URI} (.+)/$
15 | RewriteRule ^ %1 [L,R=301]
16 |
17 | # Handle Front Controller...
18 | RewriteCond %{REQUEST_FILENAME} !-d
19 | RewriteCond %{REQUEST_FILENAME} !-f
20 | RewriteRule ^ index.php [L]
21 |
22 |
--------------------------------------------------------------------------------
/resources/lang/en/auth.php:
--------------------------------------------------------------------------------
1 | 'These credentials do not match our records.',
17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
18 |
19 | ];
20 |
--------------------------------------------------------------------------------
/app/Providers/AuthServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'App\Policies\ModelPolicy',
17 | ];
18 |
19 | /**
20 | * Register any authentication / authorization services.
21 | *
22 | * @return void
23 | */
24 | public function boot()
25 | {
26 | $this->registerPolicies();
27 |
28 | //
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/resources/views/home.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 | @section('title', 'Home')
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | @if (session('status'))
12 |
13 | {{ session('status') }}
14 |
15 | @endif
16 |
17 | You are logged in!
18 |
19 |
20 |
21 |
22 |
23 | @endsection
24 |
--------------------------------------------------------------------------------
/app/Mail/OrderPlaced.php:
--------------------------------------------------------------------------------
1 | order = $order;
24 | }
25 |
26 | /**
27 | * Build the message.
28 | *
29 | * @return $this
30 | */
31 | public function build()
32 | {
33 | return $this->markdown('emails.orders.placed');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/resources/views/partials/head.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ config('app.name', 'Laravel') }} | @yield('title')
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | @yield('stylesheet')
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/ForgotPasswordController.php:
--------------------------------------------------------------------------------
1 | 'Your password has been reset!',
17 | 'sent' => 'We have e-mailed your password reset link!',
18 | 'token' => 'This password reset token is invalid.',
19 | 'user' => "We can't find a user with that e-mail address.",
20 |
21 | ];
22 |
--------------------------------------------------------------------------------
/database/seeds/RolesTableSeeder.php:
--------------------------------------------------------------------------------
1 | 'admin']);
16 | if (!$role->exists) {
17 | $role->fill([
18 | 'display_name' => __('voyager::seeders.roles.admin'),
19 | ])->save();
20 | }
21 |
22 | $role = Role::firstOrNew(['name' => 'user']);
23 | if (!$role->exists) {
24 | $role->fill([
25 | 'display_name' => __('voyager::seeders.roles.user'),
26 | ])->save();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/Order.php:
--------------------------------------------------------------------------------
1 | belongsTo('App\User');
17 | }
18 |
19 | public function products() {
20 | // adding another field on the collection when accessing the order's products
21 | return $this->belongsToMany('App\Product')->withPivot('quantity');
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_100000_create_password_resets_table.php:
--------------------------------------------------------------------------------
1 | string('email')->index();
16 | $table->string('token');
17 | $table->timestamp('created_at')->nullable();
18 | });
19 | }
20 | /**
21 | * Reverse the migrations.
22 | *
23 | * @return void
24 | */
25 | public function down()
26 | {
27 | Schema::dropIfExists('password_resets');
28 | }
29 | }
--------------------------------------------------------------------------------
/database/migrations/2019_10_19_145706_add_images_column_to_products.php:
--------------------------------------------------------------------------------
1 | text('images')->nullable()->after('image');
18 | });
19 | }
20 |
21 | /**
22 | * Reverse the migrations.
23 | *
24 | * @return void
25 | */
26 | public function down()
27 | {
28 | Schema::table('products', function (Blueprint $table) {
29 | $table->dropColumn('images');
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/database/migrations/2019_10_20_114921_create_tags_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name')->unique();
19 | $table->string('slug')->unique();
20 | $table->timestamps();
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | *
27 | * @return void
28 | */
29 | public function down()
30 | {
31 | Schema::dropIfExists('tags');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/database/seeds/VoyagerDatabaseSeeder.php:
--------------------------------------------------------------------------------
1 | call(DataTypesTableSeeder::class);
22 | $this->call(DataRowsTableSeeder::class);
23 | $this->call(MenusTableSeeder::class);
24 | $this->call(MenuItemsTableSeeder::class);
25 | $this->call(RolesTableSeeder::class);
26 | $this->call(PermissionsTableSeeder::class);
27 | $this->call(PermissionRoleTableSeeder::class);
28 | $this->call(SettingsTableSeeder::class);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/database/seeds/VoyagerDatabaseSeederCustom.php:
--------------------------------------------------------------------------------
1 | call(DataTypesTableSeederCustom::class);
22 | $this->call(DataRowsTableSeederCustom::class);
23 | $this->call(MenusTableSeederCustom::class);
24 | $this->call(MenuItemsTableSeederCustom::class);
25 | $this->call(PermissionsTableSeederCustom::class);
26 | $this->call(PermissionRoleTableSeederCustom::class);
27 | $this->call(SettingsTableSeederCustom::class);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/Providers/EventServiceProvider.php:
--------------------------------------------------------------------------------
1 | [
19 | SendEmailVerificationNotification::class,
20 | ],
21 | ];
22 |
23 | /**
24 | * Register any events for your application.
25 | *
26 | * @return void
27 | */
28 | public function boot()
29 | {
30 | parent::boot();
31 |
32 | //
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/database/migrations/2019_10_17_195112_create_categories_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name')->unique();
19 | $table->string('slug')->unique();
20 | $table->timestamps();
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | *
27 | * @return void
28 | */
29 | public function down()
30 | {
31 | Schema::dropIfExists('category');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/database/migrations/2019_11_09_002942_add_quantity_to_products_table.php:
--------------------------------------------------------------------------------
1 | unsignedInteger('quantity')->after('featured')->default(10);
18 | });
19 | }
20 |
21 | /**
22 | * Reverse the migrations.
23 | *
24 | * @return void
25 | */
26 | public function down()
27 | {
28 | Schema::table('products', function (Blueprint $table) {
29 | $table->dropColumn('quantity');
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/database/migrations/2020_06_27_012504_create_visits_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('country');
19 | $table->unsignedBigInteger('visits')->default(0);
20 | $table->timestamps();
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | *
27 | * @return void
28 | */
29 | public function down()
30 | {
31 | Schema::dropIfExists('visits');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/database/seeds/UsersTableSeeder.php:
--------------------------------------------------------------------------------
1 | firstOrFail();
21 |
22 | User::create([
23 | 'name' => 'Admin',
24 | 'email' => 'admin@admin.com',
25 | 'password' => bcrypt(config('voyager.password')),
26 | 'remember_token' => Str::random(60),
27 | 'role_id' => $role->id,
28 | ]);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/resources/views/partials/menu/main.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/ResetPasswordController.php:
--------------------------------------------------------------------------------
1 | $key,
26 | 'table_name' => null,
27 | ]);
28 | }
29 |
30 | Permission::generateFor('menus');
31 |
32 | Permission::generateFor('roles');
33 |
34 | Permission::generateFor('users');
35 |
36 | Permission::generateFor('settings');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/database/migrations/2019_08_19_000000_create_failed_jobs_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
16 | $table->text('connection');
17 | $table->text('queue');
18 | $table->longText('payload');
19 | $table->longText('exception');
20 | $table->timestamp('failed_at')->useCurrent();
21 | });
22 | }
23 | /**
24 | * Reverse the migrations.
25 | *
26 | * @return void
27 | */
28 | public function down()
29 | {
30 | Schema::dropIfExists('failed_jobs');
31 | }
32 | }
--------------------------------------------------------------------------------
/database/migrations/2019_10_18_002421_create_coupons_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('code')->unique();
19 | $table->string('type');
20 | $table->integer('value')->nullable();
21 | $table->integer('percent_off')->nullable();
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('coupons');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/library/helper.php:
--------------------------------------------------------------------------------
1 | $limit ? substr($string, 0, $limit) . ' ...' : $string;
21 | }
22 |
23 | function getStockLevel($quantity) {
24 | if($quantity > setting('site.stock_threshold')) {
25 | return 'In Stock';
26 | } else if($quantity <= setting('site.stock_threshold') && $quantity > 0) {
27 | return 'Low Stock';
28 | } else {
29 | return 'Out Of Stock';
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/database/factories/UserFactory.php:
--------------------------------------------------------------------------------
1 | define(User::class, function (Faker $faker) {
20 | return [
21 | 'name' => $faker->name,
22 | 'email' => $faker->unique()->safeEmail,
23 | 'email_verified_at' => now(),
24 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
25 | 'remember_token' => Str::random(10),
26 | ];
27 | });
28 |
--------------------------------------------------------------------------------
/database/migrations/2019_10_16_185424_create_products_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name')->unique();
19 | $table->string('slug')->unique();
20 | $table->string('details')->nullable();
21 | $table->integer('price');
22 | $table->text('description');
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('products');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/Console/Kernel.php:
--------------------------------------------------------------------------------
1 | command('inspire')
28 | // ->hourly();
29 | }
30 |
31 | /**
32 | * Register the commands for the application.
33 | *
34 | * @return void
35 | */
36 | protected function commands()
37 | {
38 | $this->load(__DIR__.'/Commands');
39 |
40 | require base_path('routes/console.php');
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/User.php:
--------------------------------------------------------------------------------
1 | 'datetime',
38 | ];
39 |
40 | public function orders() {
41 | return $this->hasMany('App\Order');
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/database/seeds/CategoryTableSeeder.php:
--------------------------------------------------------------------------------
1 | 'Laptops',
19 | 'slug' => 'laptops'
20 | ]);
21 | Category::create([
22 | 'name' => 'Desktops',
23 | 'slug' => 'desktops'
24 | ]);
25 | Category::create([
26 | 'name' => 'Phones',
27 | 'slug' => 'phones'
28 | ]);
29 | Category::create([
30 | 'name' => 'Tablets',
31 | 'slug' => 'tablets'
32 | ]);
33 | Category::create([
34 | 'name' => 'TVs',
35 | 'slug' => 'tvs'
36 | ]);
37 | Category::create([
38 | 'name' => 'Cameras',
39 | 'slug' => 'cameras'
40 | ]);
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/Http/Controllers/CouponsController.php:
--------------------------------------------------------------------------------
1 | validate($request, [
14 | 'coupon_code' => 'required'
15 | ]);
16 | $coupon = Coupon::where('code', $request->coupon_code)->first();
17 | if(!$coupon) return redirect()->route('checkout.index')->with('error', 'Invalid Coupon Code');
18 | session()->put('coupon', [
19 | 'code' => $coupon->code,
20 | 'discount' => $coupon->discount(Cart::instance('default')->subtotal())
21 | ]);
22 |
23 | return redirect()->route('checkout.index')->withSuccess('Coupon applied successfully!');
24 | }
25 |
26 |
27 | public function destroy()
28 | {
29 | session()->forget('coupon');
30 | return redirect()->route('checkout.index')->with('success', 'Coupon has been removed');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/.example.env:
--------------------------------------------------------------------------------
1 | APP_NAME=Ecommerce
2 | APP_ENV=local
3 | APP_KEY=
4 | APP_DEBUG=true
5 | APP_URL=http://localhost:8000
6 |
7 | LOG_CHANNEL=stack
8 |
9 | DB_CONNECTION=mysql
10 | DB_HOST=127.0.0.1
11 | DB_PORT=3306
12 | DB_DATABASE=
13 | DB_USERNAME=
14 | DB_PASSWORD=
15 |
16 | BROADCAST_DRIVER=log
17 | CACHE_DRIVER=file
18 | QUEUE_CONNECTION=sync
19 | SESSION_DRIVER=file
20 | SESSION_LIFETIME=120
21 |
22 | REDIS_HOST=127.0.0.1
23 | REDIS_PASSWORD=null
24 | REDIS_PORT=6379
25 |
26 | MAIL_DRIVER=smtp
27 | MAIL_HOST=smtp.mailtrap.io
28 | MAIL_PORT=2525
29 | MAIL_USERNAME=
30 | MAIL_PASSWORD=
31 | MAIL_ENCRYPTION=null
32 |
33 | AWS_ACCESS_KEY_ID=
34 | AWS_SECRET_ACCESS_KEY=
35 | AWS_DEFAULT_REGION=us-east-1
36 | AWS_BUCKET=
37 |
38 | PUSHER_APP_ID=
39 | PUSHER_APP_KEY=
40 | PUSHER_APP_SECRET=
41 | PUSHER_APP_CLUSTER=mt1
42 |
43 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
44 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
45 |
46 | VOYAGER_ADMIN_PASSWORD=password
47 |
48 | STRIPE_KEY=
49 | STRIPE_SECRET=
50 |
51 | MAIL_FROM_ADDRESS=
52 | MAIL_FROM_NAME=
53 |
54 | ALGOLIA_APP_ID=
55 | ALGOLIA_SECRET=
56 |
--------------------------------------------------------------------------------
/database/seeds/SettingsTableSeederCustom.php:
--------------------------------------------------------------------------------
1 | findSetting('site.stock_threshold');
16 | if (!$setting->exists) {
17 | $setting->fill([
18 | 'display_name' => 'Stock Threshold',
19 | 'value' => 5,
20 | 'details' => '',
21 | 'type' => 'number',
22 | 'order' => 6,
23 | 'group' => 'Site',
24 | ])->save();
25 | }
26 | }
27 |
28 | /**
29 | * [setting description].
30 | *
31 | * @param [type] $key [description]
32 | *
33 | * @return [type] [description]
34 | */
35 | protected function findSetting($key)
36 | {
37 | return Setting::firstOrNew(['key' => $key]);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/database/migrations/2019_10_20_115306_create_products_tags_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('product_id');
19 | $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
20 | $table->unsignedBigInteger('tag_id');
21 | $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('product_tag');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/resources/js/main.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){
2 | $(".hero-text").animate({left: '0px', top: '30px'}, 1500);
3 | $('.heart').click(function (e) {
4 | e.preventDefault();
5 | if($(this).find('i').attr('class') == 'fa fa-heart'){
6 | $(this).find('i').attr('class' , 'fa fa-heart-o');
7 | } else {
8 | $(this).find('i').attr('class' , 'fa fa-heart');
9 | }
10 | });
11 | $('.like').click(function (e) {
12 | e.preventDefault();
13 | if($(this).find('i').attr('class') == 'fa fa-thumbs-up'){
14 | $(this).find('i').attr('class' , 'fa fa-thumbs-o-up');
15 | } else {
16 | $(this).find('i').attr('class' , 'fa fa-thumbs-up');
17 | }
18 | });
19 | $('.cart').click(function (e) {
20 | e.preventDefault();
21 | if($(this).find('i').attr('class') == 'fa fa-shopping-cart'){
22 | $(this).find('i').attr('class' , 'fal fa-shopping-cart');
23 | } else {
24 | $(this).find('i').attr('class' , 'fa fa-shopping-cart');
25 | }
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/app/Product.php:
--------------------------------------------------------------------------------
1 | [
16 | 'products.name' => 6,
17 | 'products.details' => 3,
18 | 'products.description' => 2,
19 | ],
20 | ];
21 |
22 | protected $guarded = [];
23 |
24 | public function scopeMightAlsoLike($query) {
25 | return $query->inRandomOrder()->take(3);
26 | }
27 |
28 | public function category() {
29 | return $this->belongsTo('App\Category');
30 | }
31 |
32 | public function tags() {
33 | return $this->belongsToMany('App\Tag');
34 | }
35 |
36 | public function toSearchableArray() {
37 | $array = $this->toArray();
38 | $extraFields = [
39 | 'category' => $this->category->name
40 | ];
41 | return array_merge($array, $extraFields);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Mohammed Omer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/database/seeds/PermissionsTableSeederCustom.php:
--------------------------------------------------------------------------------
1 | $key,
26 | 'table_name' => null,
27 | ]);
28 | }
29 |
30 | Permission::generateFor('products');
31 |
32 | Permission::generateFor('category');
33 |
34 | Permission::generateFor('coupons');
35 |
36 | Permission::generateFor('tags');
37 |
38 | Permission::generateFor('product_tag');
39 |
40 | Permission::generateFor('orders');
41 |
42 | Permission::generateFor('country_visits');
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/ConfirmPasswordController.php:
--------------------------------------------------------------------------------
1 | middleware('auth');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
16 | $table->string('name');
17 | $table->string('email')->unique();
18 | $table->timestamp('email_verified_at')->nullable();
19 | $table->string('github_id')->nullable();
20 | $table->string('facebook_id')->nullable();
21 | $table->string('google_id')->nullable();
22 | $table->string('password')->nullable();
23 | $table->rememberToken();
24 | $table->timestamps();
25 | });
26 | }
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('users');
35 | }
36 | }
--------------------------------------------------------------------------------
/app/Http/Middleware/VisitsMiddleware.php:
--------------------------------------------------------------------------------
1 | country;
28 | $visit = CountryVisit::firstOrCreate([
29 | 'country' => $country
30 | ]);
31 | $visit->incrementVisits();
32 | session(['visited' => 'visited']);
33 | Session::save();
34 | }
35 | return $next($request);
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/config/view.php:
--------------------------------------------------------------------------------
1 | [
17 | resource_path('views'),
18 | ],
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Compiled View Path
23 | |--------------------------------------------------------------------------
24 | |
25 | | This option determines where all the compiled Blade templates will be
26 | | stored for your application. Typically, this is within the storage
27 | | directory. However, as usual, you are free to change this value.
28 | |
29 | */
30 |
31 | 'compiled' => env(
32 | 'VIEW_COMPILED_PATH',
33 | realpath(storage_path('framework/views'))
34 | ),
35 |
36 | ];
37 |
--------------------------------------------------------------------------------
/database/migrations/2019_10_17_195227_add_category_id_to_products_table.php:
--------------------------------------------------------------------------------
1 | string('image')->after('price');
18 | $table->boolean('featured')->default(false)->after('image');
19 | $table->unsignedBigInteger('category_id')->after('featured');
20 | $table->foreign('category_id')->references('id')->on('category')->onDelete('cascade');
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | *
27 | * @return void
28 | */
29 | public function down()
30 | {
31 | Schema::table('products', function (Blueprint $table) {
32 | $table->dropForeign('products_category_id_foreign');
33 | $table->dropColumn('image');
34 | $table->dropColumn('category_id');
35 | });
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/resources/js/app.js:
--------------------------------------------------------------------------------
1 | /**
2 | * First we will load all of this project's JavaScript dependencies which
3 | * includes Vue and other libraries. It is a great starting point when
4 | * building robust, powerful web applications using Vue and Laravel.
5 | */
6 |
7 | require('./bootstrap');
8 | require('./main');
9 |
10 | window.Vue = require('vue');
11 |
12 | /**
13 | * The following block of code may be used to automatically register your
14 | * Vue components. It will recursively scan this directory for the Vue
15 | * components and automatically register them with their "basename".
16 | *
17 | * Eg. ./components/ExampleComponent.vue ->
18 | */
19 |
20 | // const files = require.context('./', true, /\.vue$/i)
21 | // files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
22 |
23 | Vue.component('example-component', require('./components/ExampleComponent.vue').default);
24 | window.$ = require('jquery');
25 |
26 | /**
27 | * Next, we will create a fresh Vue application instance and attach it to
28 | * the page. Then, you may begin adding components to this application
29 | * or customize the JavaScript scaffolding to fit your unique needs.
30 | */
31 |
32 |
--------------------------------------------------------------------------------
/app/Http/Requests/CheckoutRequest.php:
--------------------------------------------------------------------------------
1 | user() ? 'required|email' : 'required|email|unique:users';
27 | return [
28 | 'email' => $emailValidation,
29 | 'name' => 'required|max:255|min:3',
30 | 'address' => 'required',
31 | 'city' => 'required',
32 | 'province' => 'required',
33 | 'postal_code' => 'required',
34 | 'phone' => 'required'
35 | ];
36 | }
37 |
38 | public function messages() {
39 | return [
40 | 'email.unique,users,email' => "You already have an account with this email address, Please Login "
41 | ];
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/resources/views/auth/verify.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | @if (session('resent'))
12 |
13 | {{ __('A fresh verification link has been sent to your email address.') }}
14 |
15 | @endif
16 |
17 | {{ __('Before proceeding, please check your email for a verification link.') }}
18 | {{ __('If you did not receive the email') }},
19 |
23 |
24 |
25 |
26 |
27 |
28 | @endsection
29 |
--------------------------------------------------------------------------------
/database/migrations/2019_10_22_190613_create_order_product_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('product_id')->nullable();
19 | $table->foreign('product_id')->references('id')->on('products')
20 | ->onUpdate('cascade')->onDelete('set null');
21 | $table->unsignedBigInteger('order_id')->nullable();
22 | $table->foreign('order_id')->references('id')->on('orders')
23 | ->onUpdate('cascade')->onDelete('set null');
24 | $table->unsignedInteger('quantity');
25 | $table->timestamps();
26 | });
27 | }
28 |
29 | /**
30 | * Reverse the migrations.
31 | *
32 | * @return void
33 | */
34 | public function down()
35 | {
36 | Schema::dropIfExists('order_product');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/VerificationController.php:
--------------------------------------------------------------------------------
1 | middleware('auth');
38 | $this->middleware('signed')->only('verify');
39 | $this->middleware('throttle:6,1')->only('verify', 'resend');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | ./tests/Unit
14 |
15 |
16 |
17 | ./tests/Feature
18 |
19 |
20 |
21 |
22 | ./app
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/Exceptions/Handler.php:
--------------------------------------------------------------------------------
1 | rand(1, 2) == 1? 1 : null,
22 | 'billing_email' => $faker->email,
23 | 'billing_name' => $faker->userName,
24 | 'billing_address' => $faker->secondaryAddress,
25 | 'billing_city' => $faker->city,
26 | 'billing_province' => $faker->city,
27 | 'billing_postalcode' => $faker->postcode,
28 | 'billing_phone' => $faker->phoneNumber,
29 | 'billing_name_on_card' => $faker->userName,
30 | 'billing_discount' => 0,
31 | 'billing_discount_code' => null,
32 | 'billing_subtotal' => 1000,
33 | 'billing_tax' => 200,
34 | 'billing_total' => 1200,
35 | 'shipped' => rand(0,1),
36 | 'error' => $i%4 == 0 ? 'Error' : null,
37 | ]);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "npm run development",
5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
6 | "watch": "npm run development -- --watch",
7 | "watch-poll": "npm run watch -- --watch-poll",
8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
9 | "prod": "npm run production",
10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
11 | },
12 | "devDependencies": {
13 | "axios": "^0.21.2",
14 | "bootstrap": "^4.5.0",
15 | "cross-env": "^5.1",
16 | "font-awesome": "^4.7.0",
17 | "jquery": "^3.5.1",
18 | "laravel-mix": "^4.0.7",
19 | "lodash": "^4.17.21",
20 | "popper.js": "^1.16.1",
21 | "resolve-url-loader": "^2.3.1",
22 | "sass": "^1.26.9",
23 | "sass-loader": "7.*",
24 | "vue": "^2.6.11",
25 | "vue-template-compiler": "^2.6.11"
26 | },
27 | "dependencies": {
28 | "aos": "^3.0.0-beta.6",
29 | "chart.js": "^2.9.4",
30 | "font-awesome": "^4.7.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/resources/views/partials/footer.blade.php:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/resources/views/search.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 | @section('title', 'Search')
3 | @section('content')
4 |
5 |
6 |
Showing {{ $products->count() }} results for {{ $query }} out of {{ $products->total() }}
7 | @if ($products->total() == 0)
8 |
9 | No products found for your search
10 |
11 | @else
12 |
13 |
14 |
15 | Name
16 | Price
17 | details
18 | Description
19 | Image
20 |
21 |
22 |
23 | @foreach ($products as $product)
24 |
25 | {{ $product->name }}
26 | ${{ format($product->price) }}
27 | {{ $product->details }}
28 | {{ str_limit($product->description, 70) }}
29 |
30 |
31 | @endforeach
32 |
33 |
34 | @endif
35 | {{ $products->links() }}
36 |
37 |
38 | @endsection
--------------------------------------------------------------------------------
/config/services.php:
--------------------------------------------------------------------------------
1 | [
18 | 'domain' => env('MAILGUN_DOMAIN'),
19 | 'secret' => env('MAILGUN_SECRET'),
20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
21 | ],
22 |
23 | 'postmark' => [
24 | 'token' => env('POSTMARK_TOKEN'),
25 | ],
26 |
27 | 'ses' => [
28 | 'key' => env('AWS_ACCESS_KEY_ID'),
29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'),
30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
31 | ],
32 |
33 | 'stripe' => [
34 | 'model' => App\User::class,
35 | 'key' => env('STRIPE_KEY'),
36 | 'secret' => env('STRIPE_SECRET'),
37 | ],
38 |
39 | 'github' => [
40 | 'client_id' => env('GITHUB_CLIENT_ID'),
41 | 'client_secret' => env('GITHUB_CLIENT_SECRET'),
42 | 'redirect' => env('GITHUB_CALLBACK'),
43 | ],
44 |
45 | 'facebook' => [
46 | 'client_id' => env('FACEBOOK_CLIENT_ID'),
47 | 'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
48 | 'redirect' => env('FACEBOOK_CALLBACK'),
49 | ],
50 |
51 | ];
52 |
--------------------------------------------------------------------------------
/resources/views/errors/layout.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @yield('title')
8 |
9 |
10 |
11 |
12 |
13 |
14 |
47 |
48 |
49 |
50 |
51 |
52 | @yield('message')
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/config/hashing.php:
--------------------------------------------------------------------------------
1 | 'bcrypt',
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Bcrypt Options
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may specify the configuration options that should be used when
26 | | passwords are hashed using the Bcrypt algorithm. This will allow you
27 | | to control the amount of time it takes to hash the given password.
28 | |
29 | */
30 |
31 | 'bcrypt' => [
32 | 'rounds' => env('BCRYPT_ROUNDS', 10),
33 | ],
34 |
35 | /*
36 | |--------------------------------------------------------------------------
37 | | Argon Options
38 | |--------------------------------------------------------------------------
39 | |
40 | | Here you may specify the configuration options that should be used when
41 | | passwords are hashed using the Argon algorithm. These will allow you
42 | | to control the amount of time it takes to hash the given password.
43 | |
44 | */
45 |
46 | 'argon' => [
47 | 'memory' => 1024,
48 | 'threads' => 2,
49 | 'time' => 2,
50 | ],
51 |
52 | ];
53 |
--------------------------------------------------------------------------------
/bootstrap/app.php:
--------------------------------------------------------------------------------
1 | singleton(
30 | Illuminate\Contracts\Http\Kernel::class,
31 | App\Http\Kernel::class
32 | );
33 |
34 | $app->singleton(
35 | Illuminate\Contracts\Console\Kernel::class,
36 | App\Console\Kernel::class
37 | );
38 |
39 | $app->singleton(
40 | Illuminate\Contracts\Debug\ExceptionHandler::class,
41 | App\Exceptions\Handler::class
42 | );
43 |
44 | /*
45 | |--------------------------------------------------------------------------
46 | | Return The Application
47 | |--------------------------------------------------------------------------
48 | |
49 | | This script returns the application instance. The instance is given to
50 | | the calling script so we can separate the building of the instances
51 | | from the actual running of the application and sending responses.
52 | |
53 | */
54 |
55 | return $app;
56 |
--------------------------------------------------------------------------------
/database/migrations/2019_10_22_185425_create_orders_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('user_id')->nullable();
19 | $table->foreign('user_id')->references('id')->on('users')
20 | ->onUpdate('cascade')->onDelete('set null');
21 | $table->string('billing_email');
22 | $table->string('billing_name');
23 | $table->string('billing_address');
24 | $table->string('billing_city');
25 | $table->string('billing_province');
26 | $table->string('billing_postalcode');
27 | $table->string('billing_phone');
28 | $table->string('billing_name_on_card');
29 | $table->integer('billing_discount')->default(0);
30 | $table->string('billing_discount_code')->nullable();
31 | $table->integer('billing_subtotal');
32 | $table->integer('billing_tax');
33 | $table->integer('billing_total');
34 | $table->string('payment_gateway')->default('stripe');
35 | $table->boolean('shipped')->default(false);
36 | $table->string('error')->nullable();
37 | $table->timestamps();
38 | });
39 | }
40 |
41 | /**
42 | * Reverse the migrations.
43 | *
44 | * @return void
45 | */
46 | public function down()
47 | {
48 | Schema::dropIfExists('orders');
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/config/broadcasting.php:
--------------------------------------------------------------------------------
1 | env('BROADCAST_DRIVER', 'null'),
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Broadcast Connections
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may define all of the broadcast connections that will be used
26 | | to broadcast events to other systems or over websockets. Samples of
27 | | each available type of connection are provided inside this array.
28 | |
29 | */
30 |
31 | 'connections' => [
32 |
33 | 'pusher' => [
34 | 'driver' => 'pusher',
35 | 'key' => env('PUSHER_APP_KEY'),
36 | 'secret' => env('PUSHER_APP_SECRET'),
37 | 'app_id' => env('PUSHER_APP_ID'),
38 | 'options' => [
39 | 'cluster' => env('PUSHER_APP_CLUSTER'),
40 | 'useTLS' => true,
41 | ],
42 | ],
43 |
44 | 'redis' => [
45 | 'driver' => 'redis',
46 | 'connection' => 'default',
47 | ],
48 |
49 | 'log' => [
50 | 'driver' => 'log',
51 | ],
52 |
53 | 'null' => [
54 | 'driver' => 'null',
55 | ],
56 |
57 | ],
58 |
59 | ];
60 |
--------------------------------------------------------------------------------
/app/Providers/RouteServiceProvider.php:
--------------------------------------------------------------------------------
1 | mapApiRoutes();
39 |
40 | $this->mapWebRoutes();
41 |
42 | //
43 | }
44 |
45 | /**
46 | * Define the "web" routes for the application.
47 | *
48 | * These routes all receive session state, CSRF protection, etc.
49 | *
50 | * @return void
51 | */
52 | protected function mapWebRoutes()
53 | {
54 | Route::middleware('web')
55 | ->namespace($this->namespace)
56 | ->group(base_path('routes/web.php'));
57 | }
58 |
59 | /**
60 | * Define the "api" routes for the application.
61 | *
62 | * These routes are typically stateless.
63 | *
64 | * @return void
65 | */
66 | protected function mapApiRoutes()
67 | {
68 | Route::prefix('api')
69 | ->middleware('api')
70 | ->namespace($this->namespace)
71 | ->group(base_path('routes/api.php'));
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/resources/views/errors/minimal.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @yield('title')
8 |
9 |
10 |
11 |
12 |
13 |
14 |
50 |
51 |
52 |
53 |
54 | @yield('code')
55 |
56 |
57 |
58 | @yield('message')
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/resources/views/partials/might-like.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
You might also like
4 |
5 |
6 | @foreach ($mightLike as $product)
7 |
8 |
23 |
24 | @endforeach
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/artisan:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | make(Illuminate\Contracts\Console\Kernel::class);
34 |
35 | $status = $kernel->handle(
36 | $input = new Symfony\Component\Console\Input\ArgvInput,
37 | new Symfony\Component\Console\Output\ConsoleOutput
38 | );
39 |
40 | /*
41 | |--------------------------------------------------------------------------
42 | | Shutdown The Application
43 | |--------------------------------------------------------------------------
44 | |
45 | | Once Artisan has finished running, we will fire off the shutdown events
46 | | so that any final work may be done by the application before we shut
47 | | down the process. This is the last thing to happen to the request.
48 | |
49 | */
50 |
51 | $kernel->terminate($input, $status);
52 |
53 | exit($status);
54 |
--------------------------------------------------------------------------------
/config/cart.php:
--------------------------------------------------------------------------------
1 | 21,
16 |
17 | /*
18 | |--------------------------------------------------------------------------
19 | | Shoppingcart database settings
20 | |--------------------------------------------------------------------------
21 | |
22 | | Here you can set the connection that the shoppingcart should use when
23 | | storing and restoring a cart.
24 | |
25 | */
26 |
27 | 'database' => [
28 |
29 | 'connection' => null,
30 |
31 | 'table' => 'shoppingcart',
32 |
33 | ],
34 |
35 | /*
36 | |--------------------------------------------------------------------------
37 | | Destroy the cart on user logout
38 | |--------------------------------------------------------------------------
39 | |
40 | | When this option is set to 'true' the cart will automatically
41 | | destroy all cart instances when the user logs out.
42 | |
43 | */
44 |
45 | 'destroy_on_logout' => false,
46 |
47 | /*
48 | |--------------------------------------------------------------------------
49 | | Default number format
50 | |--------------------------------------------------------------------------
51 | |
52 | | This defaults will be used for the formatted numbers if you don't
53 | | set them in the method call.
54 | |
55 | */
56 |
57 | 'format' => [
58 |
59 | 'decimals' => 0,
60 |
61 | 'decimal_point' => '',
62 |
63 | 'thousand_separator' => '',
64 |
65 | ],
66 |
67 | ];
68 |
--------------------------------------------------------------------------------
/routes/web.php:
--------------------------------------------------------------------------------
1 | middleware('admin');
9 |
10 | // Shop and welcome
11 | Route::get('/', 'WelcomePageController@index')->name('welcome');
12 | Route::get('/shop', 'ShopController@index')->name('shop.index');
13 | Route::get('/shop/{product}', 'ShopController@show')->name('shop.show');
14 | Route::get('/shop/search/{query}', 'ShopController@search')->name('shop.search');
15 |
16 |
17 | // Cart
18 | Route::get('/cart', 'CartController@index')->name('cart.index');
19 | Route::post('/cart', 'CartController@store')->name('cart.store');
20 | Route::delete('/cart/{product}/{cart}', 'CartController@destroy')->name('cart.destroy');
21 | Route::post('/cart/save-later/{product}', 'CartController@saveLater')->name('cart.save-later');
22 | Route::post('/cart/add-to-cart/{product}', 'CartController@addToCart')->name('cart.add-to-cart');
23 | Route::patch('/cart/{product}', 'CartController@update')->name('cart.update');
24 |
25 | // checkout
26 | Route::get('/checkout', 'CheckoutController@index')->name('checkout.index');
27 | Route::post('/checkout', 'CheckoutController@store')->name('checkout.store');
28 | Route::get('/guest-checkout', 'CheckoutController@index')->name('checkout.guest');
29 |
30 | // coupon
31 | Route::post('/coupon', 'CouponsController@store')->name('coupon.store');
32 | Route::delete('/coupon/', 'CouponsController@destroy')->name('coupon.destroy');
33 |
34 | // auth routes
35 | Auth::routes();
36 | Route::get('/login/{provider}', 'Auth\LoginController@redirectToProvider');
37 | Route::get('/login/{provider}/callback', 'Auth\LoginController@handleProviderCallback');
38 |
39 | Route::get('/home', 'HomeController@index')->name('home');
40 |
41 | Route::group(['prefix' => 'admin'], function () {
42 | Voyager::routes();
43 | Route::get('/country_visits', 'VisitsController@index')->name('voyager.visits');
44 | });
45 |
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 |
8 | */
9 |
10 | define('LARAVEL_START', microtime(true));
11 |
12 | /*
13 | |--------------------------------------------------------------------------
14 | | Register The Auto Loader
15 | |--------------------------------------------------------------------------
16 | |
17 | | Composer provides a convenient, automatically generated class loader for
18 | | our application. We just need to utilize it! We'll simply require it
19 | | into the script here so that we don't have to worry about manual
20 | | loading any of our classes later on. It feels great to relax.
21 | |
22 | */
23 |
24 | require __DIR__.'/../vendor/autoload.php';
25 |
26 | /*
27 | |--------------------------------------------------------------------------
28 | | Turn On The Lights
29 | |--------------------------------------------------------------------------
30 | |
31 | | We need to illuminate PHP development, so let us turn on the lights.
32 | | This bootstraps the framework and gets it ready for use, then it
33 | | will load up this application so that we can run it and send
34 | | the responses back to the browser and delight our users.
35 | |
36 | */
37 |
38 | $app = require_once __DIR__.'/../bootstrap/app.php';
39 |
40 | /*
41 | |--------------------------------------------------------------------------
42 | | Run The Application
43 | |--------------------------------------------------------------------------
44 | |
45 | | Once we have the application, we can handle the incoming request
46 | | through the kernel, and send the associated response back to
47 | | the client's browser allowing them to enjoy the creative
48 | | and wonderful application we have prepared for them.
49 | |
50 | */
51 |
52 | $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
53 |
54 | $response = $kernel->handle(
55 | $request = Illuminate\Http\Request::capture()
56 | );
57 |
58 | $response->send();
59 |
60 | $kernel->terminate($request, $response);
61 |
--------------------------------------------------------------------------------
/resources/views/auth/passwords/email.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | @if (session('status'))
12 |
13 | {{ session('status') }}
14 |
15 | @endif
16 |
17 |
42 |
43 |
44 |
45 |
46 |
47 | @endsection
48 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/RegisterController.php:
--------------------------------------------------------------------------------
1 | middleware('guest');
41 | }
42 |
43 | /**
44 | * Get a validator for an incoming registration request.
45 | *
46 | * @param array $data
47 | * @return \Illuminate\Contracts\Validation\Validator
48 | */
49 | protected function validator(array $data)
50 | {
51 | return Validator::make($data, [
52 | 'name' => ['required', 'string', 'max:255'],
53 | 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
54 | 'password' => ['required', 'string', 'min:8', 'confirmed'],
55 | ]);
56 | }
57 |
58 | /**
59 | * Create a new user instance after a valid registration.
60 | *
61 | * @param array $data
62 | * @return \App\User
63 | */
64 | protected function create(array $data)
65 | {
66 | return User::create([
67 | 'name' => $data['name'],
68 | 'email' => $data['email'],
69 | 'password' => Hash::make($data['password']),
70 | ]);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/config/filesystems.php:
--------------------------------------------------------------------------------
1 | env('FILESYSTEM_DRIVER', 'local'),
17 |
18 | /*
19 | |--------------------------------------------------------------------------
20 | | Default Cloud Filesystem Disk
21 | |--------------------------------------------------------------------------
22 | |
23 | | Many applications store files both locally and in the cloud. For this
24 | | reason, you may specify a default "cloud" driver here. This driver
25 | | will be bound as the Cloud disk implementation in the container.
26 | |
27 | */
28 |
29 | 'cloud' => env('FILESYSTEM_CLOUD', 's3'),
30 |
31 | /*
32 | |--------------------------------------------------------------------------
33 | | Filesystem Disks
34 | |--------------------------------------------------------------------------
35 | |
36 | | Here you may configure as many filesystem "disks" as you wish, and you
37 | | may even configure multiple disks of the same driver. Defaults have
38 | | been setup for each driver as an example of the required options.
39 | |
40 | | Supported Drivers: "local", "ftp", "sftp", "s3"
41 | |
42 | */
43 |
44 | 'disks' => [
45 |
46 | 'local' => [
47 | 'driver' => 'local',
48 | 'root' => storage_path('app'),
49 | ],
50 |
51 | 'public' => [
52 | 'driver' => 'local',
53 | 'root' => storage_path('app/public'),
54 | 'url' => env('APP_URL').'/storage',
55 | 'visibility' => 'public',
56 | ],
57 |
58 | 's3' => [
59 | 'driver' => 's3',
60 | 'key' => env('AWS_ACCESS_KEY_ID'),
61 | 'secret' => env('AWS_SECRET_ACCESS_KEY'),
62 | 'region' => env('AWS_DEFAULT_REGION'),
63 | 'bucket' => env('AWS_BUCKET'),
64 | 'url' => env('AWS_URL'),
65 | ],
66 |
67 | ],
68 |
69 | ];
70 |
--------------------------------------------------------------------------------
/resources/sass/_main.scss:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | font-family: 'Merienda One', cursive, sans-serif;
4 | background-color: #eee;
5 | }
6 |
7 | nav {
8 | opacity: 0.97;
9 | }
10 |
11 | .custom-border {
12 | border: 1px solid gainsboro;
13 | color: white;
14 | border-radius: 0;
15 | }
16 |
17 | .custom-border-n {
18 | border: 1px solid black;
19 | color: #222;
20 | border-radius: 0;
21 | margin-top:1em;
22 | }
23 |
24 | .custom-border-success {
25 | border-radius: 0;
26 | }
27 |
28 | .custom-border-n:hover {
29 | background-color: #222;
30 | color: white;
31 | }
32 |
33 | .product {
34 | margin-bottom: 1em;
35 | }
36 |
37 | button {
38 | margin-right: 1em;
39 | margin-top: 1em;
40 | margin-bottom: 1em;
41 | }
42 |
43 | .header {
44 | font-size: 1.7em;
45 | margin-bottom: 2em;
46 | }
47 |
48 | footer {
49 | color: white;;
50 | padding: 4em;
51 | }
52 |
53 | .footer {
54 | padding: 2em;
55 | }
56 |
57 | .card {
58 | padding: 0em;
59 | margin: 0em;
60 | }
61 |
62 | .footer-link {
63 | color: white;
64 | }
65 |
66 | .content-head {
67 | margin-bottom: 2em;
68 | }
69 |
70 | .card-body {
71 | align-content: center;
72 | justify-content: center;
73 | }
74 |
75 | a.custom-card,
76 | a.custom-card:hover {
77 | color: inherit;
78 | text-decoration: none;
79 | }
80 |
81 | .light-text {
82 | color: #444;
83 | }
84 |
85 | .suggestions {
86 | background-color: #ddd;
87 | }
88 |
89 | // from here
90 |
91 | .my-input {
92 | border-radius: 0;
93 | }
94 |
95 | .center {
96 | justify-content: center;
97 | align-content: center;
98 | }
99 |
100 | .cart-option {
101 | border: none;
102 | }
103 |
104 | .ais-SearchBox-submit, .ais-SearchBox-reset{
105 | margin: 0;
106 | }
107 |
108 | .ais-Pagination {
109 | margin-top: 2em;
110 | margin-bottom: 2em;
111 | }
112 |
113 | .ais-Stats-text {
114 | margin-bottom: 1em;
115 | }
116 |
117 | .result-head {
118 | font-size: 0.9em;
119 | }
120 |
121 | .result-details {
122 | font-size: 0.6em;
123 | color: #444;
124 | }
125 |
126 | .result-price {
127 | font-size: 0.6em;
128 | color: #444;
129 | }
130 |
131 | .image-center {
132 | display: block;
133 | margin: 0 auto;
134 | }
135 |
136 | .ais-Hits-item {
137 | width: 100%;
138 | }
--------------------------------------------------------------------------------
/app/Http/Controllers/ShopController.php:
--------------------------------------------------------------------------------
1 | category) {
17 | $category = Category::where('slug', request()->category)->get()->first();
18 | $products = Product::where('category_id', $category->id);
19 | $categoryName = $category->name;
20 | } else if(request()->tag) {
21 | $tag = Tag::where('slug', request()->tag)->get()->first();
22 | $products = $tag->products();
23 | $tagName = $tag->name;
24 | } else {
25 | $products = Product::where('featured', true);
26 | $categoryName = 'Featured';
27 | }
28 | if(request()->sort == 'low_high') {
29 | $products = $products->orderBy('price')->paginate($pagination);
30 | } else if(request()->sort == 'high_low') {
31 | $products = $products->orderBy('price', 'desc')->paginate($pagination);
32 | } else {
33 | $products = $products->inRandomOrder()->paginate($pagination);
34 | }
35 | $categories = Category::all();
36 | $tags = Tag::all();
37 | return view('shop')->with([
38 | 'products' => $products,
39 | 'categories'=> $categories,
40 | 'tags'=> $tags,
41 | 'categoryName' => $categoryName ?? null,
42 | 'tagName' => $tagName ?? null
43 | ]);
44 | }
45 |
46 | public function show($slug) {
47 | $product = Product::where('slug', $slug)->firstOrFail();
48 | $images = json_decode($product->images);
49 | $mightLike = Product::where('slug', '!=', $product->slug)->mightAlsoLike()->get();
50 | $stockLevel = getStockLevel($product->quantity);
51 | return view('product')->with([
52 | 'product' => $product,
53 | 'mightLike' => $mightLike,
54 | 'images' => $images,
55 | 'stockLevel' => $stockLevel
56 | ]);
57 | }
58 |
59 | public function search($query) {
60 | if(strlen($query) < 3) return back()->with('error', 'minimum query length is 3');
61 | $products = Product::search($query)->paginate(10);
62 | return view('search')->with(['products' => $products, 'query' => $query]);
63 | }
64 |
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ecommerce-laravel-fullstack
2 |
3 | # Link : http://vampireecommerce.herokuapp.com
4 |
5 | This repo is based on the [youtube series](https://www.youtube.com/playlist?list=PLEhEHUEU3x5oPTli631ZX9cxl6cU_sDaR) by [@drehimself](https://github.com/drehimself)
6 |
7 | ## Features
8 |
9 | - Fully functional E-commerce website front-end and back-end built from scratch.
10 | - Using laravel voyager as an admin panel for the site.
11 | - javascript, jquery, bootstrap and css for the front-end.
12 | - Intelligent searching mechanism for products.
13 | - Awesome Cart package that uses session.
14 | - An artisan command to seed the database with all neccessary dummy data, even for voyager tables (php artisan ecommerce:install).
15 | - Different user roles and privileges.
16 | - Categories, tags and price filtering for easier search for products.
17 | - And much more features.
18 |
19 | ---
20 |
21 | ## Installation Guide
22 |
23 | 1. clone this repo to your local machine: `git clone https://github.com/mhmdomer/ecommerce-laravel.git && cd ecommerce-laravel`
24 | 1. copy `.example.env` to `.env` file: `cp .example.env .env`
25 | 1. create a new database and add the database credentials to your `.env` file
26 | 1. run `composer install`
27 | 1. run `npm install && npm run dev`
28 | 1. run `php artisan key:generate`
29 | 1. run `php artisan ecommerce:install`
30 | 1. run `php artisan serve` and then visit `http://127.0.0.1:8000/`
31 | 1. credentials to access admin panel (email: `admin@admin.com`, password: `password`)
32 | 1. after you login as admin, you can access the admin page from `http://127.0.0.1:8000/admin`
33 | - Home Page
34 |
35 | 
36 |
37 | - Shopping Page
38 |
39 | 
40 |
41 | - Cart Page
42 |
43 | 
44 |
45 | - Checkout page
46 |
47 | 
48 |
49 | - Admin Orders BREAD
50 |
51 | 
52 |
53 | - Admin Products BREAD
54 |
55 | 
56 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "laravel/laravel",
3 | "type": "project",
4 | "description": "The Laravel Framework.",
5 | "keywords": [
6 | "framework",
7 | "laravel"
8 | ],
9 | "license": "MIT",
10 | "require": {
11 | "php": "^7.3|^8.0",
12 | "bumbummen99/shoppingcart": "^2.8",
13 | "cartalyst/stripe-laravel": "^13.0",
14 | "fideloper/proxy": "^4.0",
15 | "fzaninotto/faker": "^1.4",
16 | "laravel/framework": "^8.0",
17 | "laravel/socialite": "^5.0",
18 | "laravel/tinker": "^2.0",
19 | "laravel/ui": "^3.0",
20 | "mhmdomer/laravel-database-backup": "^0.3.1",
21 | "nicolaslopezj/searchable": "^1.12",
22 | "predis/predis": "^1.1",
23 | "rap2hpoutre/laravel-log-viewer": "^1.7",
24 | "tcg/voyager": "^1.3",
25 | "torann/geoip": "^3.0"
26 | },
27 | "require-dev": {
28 | "barryvdh/laravel-debugbar": "^3.3",
29 | "facade/ignition": "^2.3.6",
30 | "mockery/mockery": "^1.0",
31 | "nunomaduro/collision": "^5.0",
32 | "phpunit/phpunit": "^9.0"
33 | },
34 | "config": {
35 | "optimize-autoloader": true,
36 | "preferred-install": "dist",
37 | "sort-packages": true
38 | },
39 | "extra": {
40 | "laravel": {
41 | "dont-discover": []
42 | }
43 | },
44 | "autoload": {
45 | "files": [
46 | "app/library/helper.php"
47 | ],
48 | "psr-4": {
49 | "App\\": "app/",
50 | "Database\\Factories\\": "database/factories/",
51 | "Database\\Seeders\\": "database/seeds/"
52 | },
53 | "classmap": [
54 | "database/seeds",
55 | "database/factories"
56 | ]
57 | },
58 | "autoload-dev": {
59 | "psr-4": {
60 | "Tests\\": "tests/"
61 | }
62 | },
63 | "minimum-stability": "dev",
64 | "prefer-stable": true,
65 | "scripts": {
66 | "post-autoload-dump": [
67 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
68 | "@php artisan package:discover --ansi"
69 | ],
70 | "post-root-package-install": [
71 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
72 | ],
73 | "post-create-project-cmd": [
74 | "@php artisan key:generate --ansi"
75 | ]
76 | },
77 | "repositories": {
78 | "hooks": {
79 | "type": "composer",
80 | "url": "https://larapack.io"
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/LoginController.php:
--------------------------------------------------------------------------------
1 | middleware('guest')->except('logout');
40 | }
41 |
42 | /**
43 | * Redirect the user to the GitHub authentication page.
44 | *
45 | * @return \Illuminate\Http\Response
46 | */
47 | public function redirectToProvider()
48 | {
49 | return Socialite::driver(request()->provider)->redirect();
50 | }
51 |
52 | /**
53 | * Obtain the user information from GitHub.
54 | *
55 | * @return \Illuminate\Http\Response
56 | */
57 | public function handleProviderCallback()
58 | {
59 | $provider = request()->provider;
60 | $providerUser = Socialite::driver($provider)->user();
61 | if($providerUser->getEmail() == null) {
62 | $user = User::where($provider . '_id', $providerUser->getId())->first();
63 | } else {
64 | $user = User::where('email', $providerUser->getEmail())->first();
65 | }
66 | if($user && $user->$provider . '_id' == null) {
67 | dd('test');
68 | $user->update([$provider . '_id' => $providerUser->getId()]);
69 | }
70 | if(!$user) {
71 | $user = User::create([
72 | 'email' => $providerUser->getEmail(),
73 | 'name' => $providerUser->getName(),
74 | $provider . '_id' => $providerUser->getId(),
75 | ]);
76 | }
77 |
78 | auth()->login($user, true);
79 |
80 | return redirect($this->redirectTo);
81 |
82 | // $user->token;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/Console/Commands/EcommerceInstall.php:
--------------------------------------------------------------------------------
1 | option('force')) {
42 | $this->proceed();
43 | } else if($this->confirm('This will delete all your current data and database and install the default dummy data Are You Sure?')) {
44 | $this->proceed();
45 | }
46 | }
47 |
48 | protected function proceed() {
49 | $linkFile = public_path('storage');
50 | if(file_exists($linkFile)) {
51 | if(is_link($linkFile)){
52 | unlink($linkFile);
53 | }
54 | }
55 | if(!file_exists(storage_path('app/public'))) {
56 | mkdir(storage_path('app/public/'));
57 | }
58 | $this->call('storage:link');
59 | $copySuccess1 = File::copyDirectory(public_path('/images/products/dummy'), public_path('storage/products/dummy'));
60 | $copySuccess2 = File::copyDirectory(public_path('/images/users'), public_path('storage/users'));
61 | if($copySuccess1 && $copySuccess2) {
62 | $this->info('Images successfully moved to storage folder');
63 | }
64 | $this->call('migrate:fresh', [
65 | '--seed' => true
66 | ]);
67 | $this->info('cleared the database and seeded basic tables successfully');
68 | $this->call('db:seed', [
69 | '--class' => 'VoyagerDatabaseSeeder'
70 | ]);
71 | $this->call('db:seed', [
72 | '--class' => 'VoyagerDummyDatabaseSeeder'
73 | ]);
74 | $this->call('db:seed', [
75 | '--class' => 'VoyagerDatabaseSeederCustom'
76 | ]);
77 | $this->call('db:seed', [
78 | '--class' => 'OrdersTableSeeder'
79 | ]);
80 | $this->call('db:seed', [
81 | '--class' => 'OrderProductTableSeeder'
82 | ]);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/database/seeds/DataTypesTableSeeder.php:
--------------------------------------------------------------------------------
1 | dataType('slug', 'users');
16 | if (!$dataType->exists) {
17 | $dataType->fill([
18 | 'name' => 'users',
19 | 'display_name_singular' => __('voyager::seeders.data_types.user.singular'),
20 | 'display_name_plural' => __('voyager::seeders.data_types.user.plural'),
21 | 'icon' => 'voyager-person',
22 | 'model_name' => 'TCG\\Voyager\\Models\\User',
23 | 'policy_name' => 'TCG\\Voyager\\Policies\\UserPolicy',
24 | 'controller' => 'TCG\\Voyager\\Http\\Controllers\\VoyagerUserController',
25 | 'generate_permissions' => 1,
26 | 'description' => '',
27 | ])->save();
28 | }
29 |
30 | $dataType = $this->dataType('slug', 'menus');
31 | if (!$dataType->exists) {
32 | $dataType->fill([
33 | 'name' => 'menus',
34 | 'display_name_singular' => __('voyager::seeders.data_types.menu.singular'),
35 | 'display_name_plural' => __('voyager::seeders.data_types.menu.plural'),
36 | 'icon' => 'voyager-list',
37 | 'model_name' => 'TCG\\Voyager\\Models\\Menu',
38 | 'controller' => '',
39 | 'generate_permissions' => 1,
40 | 'description' => '',
41 | ])->save();
42 | }
43 |
44 | $dataType = $this->dataType('slug', 'roles');
45 | if (!$dataType->exists) {
46 | $dataType->fill([
47 | 'name' => 'roles',
48 | 'display_name_singular' => __('voyager::seeders.data_types.role.singular'),
49 | 'display_name_plural' => __('voyager::seeders.data_types.role.plural'),
50 | 'icon' => 'voyager-lock',
51 | 'model_name' => 'TCG\\Voyager\\Models\\Role',
52 | 'controller' => '',
53 | 'generate_permissions' => 1,
54 | 'description' => '',
55 | ])->save();
56 | }
57 | }
58 |
59 | /**
60 | * [dataType description].
61 | *
62 | * @param [type] $field [description]
63 | * @param [type] $for [description]
64 | *
65 | * @return [type] [description]
66 | */
67 | protected function dataType($field, $for)
68 | {
69 | return DataType::firstOrNew([$field => $for]);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Voyager/OrdersController.php:
--------------------------------------------------------------------------------
1 | getSlug($request);
35 |
36 | $dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
37 |
38 | $isSoftDeleted = false;
39 |
40 | if (strlen($dataType->model_name) != 0) {
41 | $model = app($dataType->model_name);
42 |
43 | // Use withTrashed() if model uses SoftDeletes and if toggle is selected
44 | if ($model && in_array(SoftDeletes::class, class_uses($model))) {
45 | $model = $model->withTrashed();
46 | }
47 | if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) {
48 | $model = $model->{$dataType->scope}();
49 | }
50 | $dataTypeContent = call_user_func([$model, 'findOrFail'], $id);
51 | if ($dataTypeContent->deleted_at) {
52 | $isSoftDeleted = true;
53 | }
54 | } else {
55 | // If Model doest exist, get data from table name
56 | $dataTypeContent = DB::table($dataType->name)->where('id', $id)->first();
57 | }
58 |
59 | // Replace relationships' keys for labels and create READ links if a slug is provided.
60 | $dataTypeContent = $this->resolveRelations($dataTypeContent, $dataType, true);
61 |
62 | // If a column has a relationship associated with it, we do not want to show that field
63 | $this->removeRelationshipField($dataType, 'read');
64 |
65 | // Check permission
66 | $this->authorize('read', $dataTypeContent);
67 |
68 | // Check if BREAD is Translatable
69 | $isModelTranslatable = is_bread_translatable($dataTypeContent);
70 |
71 | $view = 'voyager::bread.read';
72 |
73 | if (view()->exists("voyager::$slug.read")) {
74 | $view = "voyager::$slug.read";
75 | }
76 |
77 | $products = Order::find($id)->products;
78 |
79 | return Voyager::view($view, compact('dataType', 'dataTypeContent', 'isModelTranslatable', 'isSoftDeleted', 'products'));
80 | }
81 |
82 | }
--------------------------------------------------------------------------------
/resources/views/product.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 | @section('title', $product->name)
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | @if ($images)
14 |
15 | @foreach ($images as $image)
16 |
17 |
18 |
19 | @endforeach
20 | @endif
21 |
22 |
23 |
24 |
{{ $product->name }}
25 |
{{ $stockLevel }}
26 |
{{ $product->details }}
27 |
$ {{ format($product->price) }}
28 |
{!! $product->description !!}
29 | @if ($product->quantity > 0)
30 |
37 | @endif
38 |
39 |
40 |
41 |
42 | @include('partials.might-like')
43 |
44 |
45 | @endsection
46 |
47 | @section('scripts')
48 |
49 |
69 |
70 | @endsection
71 |
--------------------------------------------------------------------------------
/config/queue.php:
--------------------------------------------------------------------------------
1 | env('QUEUE_CONNECTION', 'sync'),
17 |
18 | /*
19 | |--------------------------------------------------------------------------
20 | | Queue Connections
21 | |--------------------------------------------------------------------------
22 | |
23 | | Here you may configure the connection information for each server that
24 | | is used by your application. A default configuration has been added
25 | | for each back-end shipped with Laravel. You are free to add more.
26 | |
27 | | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
28 | |
29 | */
30 |
31 | 'connections' => [
32 |
33 | 'sync' => [
34 | 'driver' => 'sync',
35 | ],
36 |
37 | 'database' => [
38 | 'driver' => 'database',
39 | 'table' => 'jobs',
40 | 'queue' => 'default',
41 | 'retry_after' => 90,
42 | ],
43 |
44 | 'beanstalkd' => [
45 | 'driver' => 'beanstalkd',
46 | 'host' => 'localhost',
47 | 'queue' => 'default',
48 | 'retry_after' => 90,
49 | 'block_for' => 0,
50 | ],
51 |
52 | 'sqs' => [
53 | 'driver' => 'sqs',
54 | 'key' => env('AWS_ACCESS_KEY_ID'),
55 | 'secret' => env('AWS_SECRET_ACCESS_KEY'),
56 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
57 | 'queue' => env('SQS_QUEUE', 'your-queue-name'),
58 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
59 | ],
60 |
61 | 'redis' => [
62 | 'driver' => 'redis',
63 | 'connection' => 'default',
64 | 'queue' => env('REDIS_QUEUE', 'default'),
65 | 'retry_after' => 90,
66 | 'block_for' => null,
67 | ],
68 |
69 | ],
70 |
71 | /*
72 | |--------------------------------------------------------------------------
73 | | Failed Queue Jobs
74 | |--------------------------------------------------------------------------
75 | |
76 | | These options configure the behavior of failed queue job logging so you
77 | | can control which database and table are used to store the jobs that
78 | | have failed. You may change them to any database / table you wish.
79 | |
80 | */
81 |
82 | 'failed' => [
83 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
84 | 'database' => env('DB_CONNECTION', 'mysql'),
85 | 'table' => 'failed_jobs',
86 | ],
87 |
88 | ];
89 |
--------------------------------------------------------------------------------
/resources/views/partials/nav.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
53 |
54 |
55 |
60 |
73 |
--------------------------------------------------------------------------------
/config/logging.php:
--------------------------------------------------------------------------------
1 | env('LOG_CHANNEL', 'stack'),
21 |
22 | /*
23 | |--------------------------------------------------------------------------
24 | | Log Channels
25 | |--------------------------------------------------------------------------
26 | |
27 | | Here you may configure the log channels for your application. Out of
28 | | the box, Laravel uses the Monolog PHP logging library. This gives
29 | | you a variety of powerful log handlers / formatters to utilize.
30 | |
31 | | Available Drivers: "single", "daily", "slack", "syslog",
32 | | "errorlog", "monolog",
33 | | "custom", "stack"
34 | |
35 | */
36 |
37 | 'channels' => [
38 | 'stack' => [
39 | 'driver' => 'stack',
40 | 'channels' => ['daily'],
41 | 'ignore_exceptions' => false,
42 | ],
43 |
44 | 'single' => [
45 | 'driver' => 'single',
46 | 'path' => storage_path('logs/laravel.log'),
47 | 'level' => 'debug',
48 | ],
49 |
50 | 'daily' => [
51 | 'driver' => 'daily',
52 | 'path' => storage_path('logs/laravel.log'),
53 | 'level' => 'debug',
54 | 'days' => 14,
55 | ],
56 |
57 | 'slack' => [
58 | 'driver' => 'slack',
59 | 'url' => env('LOG_SLACK_WEBHOOK_URL'),
60 | 'username' => 'Laravel Log',
61 | 'emoji' => ':boom:',
62 | 'level' => 'critical',
63 | ],
64 |
65 | 'papertrail' => [
66 | 'driver' => 'monolog',
67 | 'level' => 'debug',
68 | 'handler' => SyslogUdpHandler::class,
69 | 'handler_with' => [
70 | 'host' => env('PAPERTRAIL_URL'),
71 | 'port' => env('PAPERTRAIL_PORT'),
72 | ],
73 | ],
74 |
75 | 'stderr' => [
76 | 'driver' => 'monolog',
77 | 'handler' => StreamHandler::class,
78 | 'formatter' => env('LOG_STDERR_FORMATTER'),
79 | 'with' => [
80 | 'stream' => 'php://stderr',
81 | ],
82 | ],
83 |
84 | 'syslog' => [
85 | 'driver' => 'syslog',
86 | 'level' => 'debug',
87 | ],
88 |
89 | 'errorlog' => [
90 | 'driver' => 'errorlog',
91 | 'level' => 'debug',
92 | ],
93 |
94 | 'null' => [
95 | 'driver' => 'monolog',
96 | 'handler' => NullHandler::class,
97 | ],
98 | ],
99 |
100 | ];
101 |
--------------------------------------------------------------------------------
/resources/views/auth/passwords/reset.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
65 | @endsection
66 |
--------------------------------------------------------------------------------
/config/scout.php:
--------------------------------------------------------------------------------
1 | env('SCOUT_DRIVER', 'algolia'),
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Index Prefix
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may specify a prefix that will be applied to all search index
26 | | names used by Scout. This prefix may be useful if you have multiple
27 | | "tenants" or applications sharing the same search infrastructure.
28 | |
29 | */
30 |
31 | 'prefix' => env('SCOUT_PREFIX', ''),
32 |
33 | /*
34 | |--------------------------------------------------------------------------
35 | | Queue Data Syncing
36 | |--------------------------------------------------------------------------
37 | |
38 | | This option allows you to control if the operations that sync your data
39 | | with your search engines are queued. When this is set to "true" then
40 | | all automatic data syncing will get queued for better performance.
41 | |
42 | */
43 |
44 | 'queue' => env('SCOUT_QUEUE', false),
45 |
46 | /*
47 | |--------------------------------------------------------------------------
48 | | Chunk Sizes
49 | |--------------------------------------------------------------------------
50 | |
51 | | These options allow you to control the maximum chunk size when you are
52 | | mass importing data into the search engine. This allows you to fine
53 | | tune each of these chunk sizes based on the power of the servers.
54 | |
55 | */
56 |
57 | 'chunk' => [
58 | 'searchable' => 500,
59 | 'unsearchable' => 500,
60 | ],
61 |
62 | /*
63 | |--------------------------------------------------------------------------
64 | | Soft Deletes
65 | |--------------------------------------------------------------------------
66 | |
67 | | This option allows to control whether to keep soft deleted records in
68 | | the search indexes. Maintaining soft deleted records can be useful
69 | | if your application still needs to search for the records later.
70 | |
71 | */
72 |
73 | 'soft_delete' => false,
74 |
75 | /*
76 | |--------------------------------------------------------------------------
77 | | Algolia Configuration
78 | |--------------------------------------------------------------------------
79 | |
80 | | Here you may configure your Algolia settings. Algolia is a cloud hosted
81 | | search engine which works great with Scout out of the box. Just plug
82 | | in your application ID and admin API key to get started searching.
83 | |
84 | */
85 |
86 | 'algolia' => [
87 | 'id' => env('ALGOLIA_APP_ID', ''),
88 | 'secret' => env('ALGOLIA_SECRET', ''),
89 | ],
90 |
91 | ];
92 |
--------------------------------------------------------------------------------
/app/Console/Commands/HerokuSetup.php:
--------------------------------------------------------------------------------
1 | option('force')) {
42 | $this->proceed();
43 | } else if($this->confirm('This will delete all your current data and database and install the default dummy data Are You Sure?')) {
44 | $this->proceed();
45 | }
46 | }
47 |
48 | protected function proceed() {
49 | File::deleteDirectory(public_path('storage/products/dummy'));
50 | File::deleteDirectory(public_path('storage/users'));
51 | $this->info(file_exists(public_path('/images/products')));
52 | $this->callSilent('storage:link');
53 | $copySuccess1 = File::copyDirectory(public_path('/images/products'), public_path('storage/products/dummy'));
54 | $copySuccess2 = File::copyDirectory(public_path('/images/users'), public_path('storage/users'));
55 | if($copySuccess1 && $copySuccess2) {
56 | $this->info('Images successfully moved to storage folder');
57 | }
58 | // $this->call('migrate:refresh', [
59 | // '--seed' => true
60 | // ]);
61 | // $this->info('cleared the database and seeded basic tables successfully');
62 | // $this->call('db:seed', [
63 | // '--class' => 'VoyagerDatabaseSeeder'
64 | // ]);
65 | // $this->call('db:seed', [
66 | // '--class' => 'VoyagerDummyDatabaseSeeder'
67 | // ]);
68 | // $this->call('db:seed', [
69 | // '--class' => 'DataTypesTableSeederCustom'
70 | // ]);
71 | // $this->call('db:seed', [
72 | // '--class' => 'DataRowsTableSeederCustom'
73 | // ]);
74 | // $this->call('db:seed', [
75 | // '--class' => 'MenusTableSeederCustom'
76 | // ]);
77 | // $this->call('db:seed', [
78 | // '--class' => 'MenuItemsTableSeederCustom'
79 | // ]);
80 | // $this->call('db:seed', [
81 | // '--class' => 'PermissionsTableSeederCustom'
82 | // ]);
83 | // $this->call('db:seed', [
84 | // '--class' => 'PermissionRoleTableSeederCustom'
85 | // ]);
86 | // $this->call('db:seed', [
87 | // '--class' => 'SettingsTableSeederCustom'
88 | // ]);
89 | // $this->call('db:seed', [
90 | // '--class' => 'OrdersTableSeeder'
91 | // ]);
92 | // $this->call('db:seed', [
93 | // '--class' => 'OrderProductTableSeeder'
94 | // ]);
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/app/Http/Kernel.php:
--------------------------------------------------------------------------------
1 | [
32 | \App\Http\Middleware\EncryptCookies::class,
33 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
34 | \Illuminate\Session\Middleware\StartSession::class,
35 | // \Illuminate\Session\Middleware\AuthenticateSession::class,
36 | \Illuminate\View\Middleware\ShareErrorsFromSession::class,
37 | \App\Http\Middleware\VerifyCsrfToken::class,
38 | \Illuminate\Routing\Middleware\SubstituteBindings::class,
39 | \App\Http\Middleware\VisitsMiddleware::class,
40 | ],
41 |
42 | 'api' => [
43 | 'throttle:60,1',
44 | 'bindings',
45 | ],
46 | ];
47 |
48 | /**
49 | * The application's route middleware.
50 | *
51 | * These middleware may be assigned to groups or used individually.
52 | *
53 | * @var array
54 | */
55 | protected $routeMiddleware = [
56 | 'auth' => \App\Http\Middleware\Authenticate::class,
57 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
58 | 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
59 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
60 | 'can' => \Illuminate\Auth\Middleware\Authorize::class,
61 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
62 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
63 | 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
64 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
65 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
66 | 'admin' => AdminMiddleware::class,
67 | ];
68 |
69 | /**
70 | * The priority-sorted list of middleware.
71 | *
72 | * This forces non-global middleware to always be in the given order.
73 | *
74 | * @var array
75 | */
76 | protected $middlewarePriority = [
77 | \Illuminate\Session\Middleware\StartSession::class,
78 | \Illuminate\View\Middleware\ShareErrorsFromSession::class,
79 | \App\Http\Middleware\Authenticate::class,
80 | \Illuminate\Routing\Middleware\ThrottleRequests::class,
81 | \Illuminate\Session\Middleware\AuthenticateSession::class,
82 | \Illuminate\Routing\Middleware\SubstituteBindings::class,
83 | \Illuminate\Auth\Middleware\Authorize::class,
84 | ];
85 | }
86 |
--------------------------------------------------------------------------------
/config/cache.php:
--------------------------------------------------------------------------------
1 | env('CACHE_DRIVER', 'file'),
22 |
23 | /*
24 | |--------------------------------------------------------------------------
25 | | Cache Stores
26 | |--------------------------------------------------------------------------
27 | |
28 | | Here you may define all of the cache "stores" for your application as
29 | | well as their drivers. You may even define multiple stores for the
30 | | same cache driver to group types of items stored in your caches.
31 | |
32 | */
33 |
34 | 'stores' => [
35 |
36 | 'apc' => [
37 | 'driver' => 'apc',
38 | ],
39 |
40 | 'array' => [
41 | 'driver' => 'array',
42 | ],
43 |
44 | 'database' => [
45 | 'driver' => 'database',
46 | 'table' => 'cache',
47 | 'connection' => null,
48 | ],
49 |
50 | 'file' => [
51 | 'driver' => 'file',
52 | 'path' => storage_path('framework/cache/data'),
53 | ],
54 |
55 | 'memcached' => [
56 | 'driver' => 'memcached',
57 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
58 | 'sasl' => [
59 | env('MEMCACHED_USERNAME'),
60 | env('MEMCACHED_PASSWORD'),
61 | ],
62 | 'options' => [
63 | // Memcached::OPT_CONNECT_TIMEOUT => 2000,
64 | ],
65 | 'servers' => [
66 | [
67 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'),
68 | 'port' => env('MEMCACHED_PORT', 11211),
69 | 'weight' => 100,
70 | ],
71 | ],
72 | ],
73 |
74 | 'redis' => [
75 | 'driver' => 'redis',
76 | 'connection' => 'cache',
77 | ],
78 |
79 | 'dynamodb' => [
80 | 'driver' => 'dynamodb',
81 | 'key' => env('AWS_ACCESS_KEY_ID'),
82 | 'secret' => env('AWS_SECRET_ACCESS_KEY'),
83 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
84 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
85 | 'endpoint' => env('DYNAMODB_ENDPOINT'),
86 | ],
87 |
88 | ],
89 |
90 | /*
91 | |--------------------------------------------------------------------------
92 | | Cache Key Prefix
93 | |--------------------------------------------------------------------------
94 | |
95 | | When utilizing a RAM based store such as APC or Memcached, there might
96 | | be other applications utilizing the same cache. So, we'll specify a
97 | | value to get prefixed to all our keys so we can avoid collisions.
98 | |
99 | */
100 |
101 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
102 |
103 | ];
104 |
--------------------------------------------------------------------------------
/resources/views/admin/visits.blade.php:
--------------------------------------------------------------------------------
1 | @extends('voyager::master')
2 |
3 | @section('head')
4 |
5 | @endsection
6 | @section('content')
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Country Visits:
22 |
23 |
24 |
25 |
26 |
27 | Country
28 | Visits
29 |
30 |
31 |
32 | @foreach ($CountryVisit as $visit)
33 |
34 | {{ $visit->country }}
35 | {{ $visit->visits }}
36 |
37 | @endforeach
38 |
39 |
40 | {{ $CountryVisit->links() }}
41 |
42 |
43 | @endsection
44 |
45 | @section('javascript')
46 |
47 |
99 |
100 |
101 | @endsection
102 |
--------------------------------------------------------------------------------
/app/Http/Controllers/CartController.php:
--------------------------------------------------------------------------------
1 | get();
14 | return view('cart')->with('mightLike', $mightLike);
15 | }
16 |
17 | public function store() {
18 | session()->forget('coupon');
19 | $duplicates = Cart::instance('default')->search(function($cartItem, $rowId) {
20 | return $cartItem->id == request()->id;
21 | });
22 | $duplicatesLater = Cart::instance('saveForLater')->search(function($cartItem, $rowId) {
23 | return $cartItem->id == request()->id;
24 | });
25 | if($duplicates->isNotEmpty()) {
26 | session()->flash('success', 'Item is already in your cart');
27 | return redirect()->route('cart.index');
28 | } else if($duplicatesLater->isNotEmpty()) {
29 | Cart::instance('saveForLater')->remove($duplicatesLater->first()->rowId);
30 | }
31 | Cart::instance('default')->add(request()->id, request()->name, 1, request()->price)->associate('App\Product');
32 | session()->flash('success', 'product added to the cart');
33 | return redirect()->route('cart.index');
34 | }
35 |
36 | public function update($id) {
37 | session()->forget('coupon');
38 | // dd(request()->all());
39 | if(request()->productQuantity >= request()->quantity) {
40 | Cart::instance('default')->update($id, request()->quantity);
41 | session()->flash('success', 'quantity updated successfully!');
42 | return response()->json(['success' => ''], 200);
43 | }
44 | session()->flash('error', 'not enough products');
45 | return response()->json(['error' => ''], 405);
46 | }
47 |
48 | public function destroy($id, $cart) {
49 | if($cart == 'default')
50 | Cart::instance('default')->remove($id);
51 | else if($cart = 'saveForLater')
52 | Cart::instance('saveForLater')->remove($id);
53 | session()->flash('success', 'item has been removed');
54 | return back();
55 | }
56 |
57 | public function saveLater($id) {
58 | session()->forget('coupon');
59 | $item = Cart::get($id);
60 | Cart::remove($id);
61 | $duplicates = Cart::instance('saveForLater')->search(function($cartItem, $rowId) use ($id) {
62 | return $rowId == $id;
63 | });
64 | if($duplicates->isNotEmpty()) {
65 | session()->flash('success', 'Item is already saved for later');
66 | return redirect()->route('cart.index');
67 | }
68 | Cart::instance('saveForLater')->add($item->id, $item->name, 1, $item->price)->associate('App\Product');
69 | session()->flash('success', 'Item has been saved for later');
70 | return redirect()->route('cart.index');
71 | }
72 |
73 | public function addToCart($id) {
74 | session()->forget('coupon');
75 | $item = Cart::instance('saveForLater')->get($id);
76 | Cart::instance('saveForLater')->remove($id);
77 | $exist = Cart::instance('default')->search(function($cartItem, $rowId) use($item) {
78 | return $cartItem->id == $item->id;
79 | });
80 | if($exist->isNotEmpty()) {
81 | session()->flash('success', 'Item is already in the cart');
82 | return redirect()->route('cart.index');
83 | }
84 | Cart::instance('default')->add($item->id, $item->name, 1, $item->price)->associate('App\Product');
85 | session()->flash('success', 'item added to the cart');
86 | return redirect()->route('cart.index');
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/resources/views/auth/register.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
77 | @endsection
78 |
--------------------------------------------------------------------------------
/config/auth.php:
--------------------------------------------------------------------------------
1 | [
17 | 'guard' => 'web',
18 | 'passwords' => 'users',
19 | ],
20 |
21 | /*
22 | |--------------------------------------------------------------------------
23 | | Authentication Guards
24 | |--------------------------------------------------------------------------
25 | |
26 | | Next, you may define every authentication guard for your application.
27 | | Of course, a great default configuration has been defined for you
28 | | here which uses session storage and the Eloquent user provider.
29 | |
30 | | All authentication drivers have a user provider. This defines how the
31 | | users are actually retrieved out of your database or other storage
32 | | mechanisms used by this application to persist your user's data.
33 | |
34 | | Supported: "session", "token"
35 | |
36 | */
37 |
38 | 'guards' => [
39 | 'web' => [
40 | 'driver' => 'session',
41 | 'provider' => 'users',
42 | ],
43 |
44 | 'api' => [
45 | 'driver' => 'token',
46 | 'provider' => 'users',
47 | 'hash' => false,
48 | ],
49 | ],
50 |
51 | /*
52 | |--------------------------------------------------------------------------
53 | | User Providers
54 | |--------------------------------------------------------------------------
55 | |
56 | | All authentication drivers have a user provider. This defines how the
57 | | users are actually retrieved out of your database or other storage
58 | | mechanisms used by this application to persist your user's data.
59 | |
60 | | If you have multiple user tables or models you may configure multiple
61 | | sources which represent each model / table. These sources may then
62 | | be assigned to any extra authentication guards you have defined.
63 | |
64 | | Supported: "database", "eloquent"
65 | |
66 | */
67 |
68 | 'providers' => [
69 | 'users' => [
70 | 'driver' => 'eloquent',
71 | 'model' => App\User::class,
72 | ],
73 |
74 | // 'users' => [
75 | // 'driver' => 'database',
76 | // 'table' => 'users',
77 | // ],
78 | ],
79 |
80 | /*
81 | |--------------------------------------------------------------------------
82 | | Resetting Passwords
83 | |--------------------------------------------------------------------------
84 | |
85 | | You may specify multiple password reset configurations if you have more
86 | | than one user table or model in the application and you want to have
87 | | separate password reset settings based on the specific user types.
88 | |
89 | | The expire time is the number of minutes that the reset token should be
90 | | considered valid. This security feature keeps tokens short-lived so
91 | | they have less time to be guessed. You may change this as needed.
92 | |
93 | */
94 |
95 | 'passwords' => [
96 | 'users' => [
97 | 'provider' => 'users',
98 | 'table' => 'password_resets',
99 | 'expire' => 60,
100 | ],
101 | ],
102 |
103 | /*
104 | |--------------------------------------------------------------------------
105 | | Password Confirmation Timeout
106 | |--------------------------------------------------------------------------
107 | |
108 | | Here you may define the amount of seconds before a password confirmation
109 | | times out and the user is prompted to re-enter their password via the
110 | | confirmation screen. By default, the timeout lasts for three hours.
111 | |
112 | */
113 |
114 | 'password_timeout' => 10800,
115 |
116 | ];
117 |
--------------------------------------------------------------------------------
/resources/views/auth/login.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
84 | @endsection
85 |
--------------------------------------------------------------------------------
/resources/views/shop.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('title', 'Shop')
4 | @section('content')
5 |
6 |
7 |
8 |
9 |
10 |
28 |
29 |
30 |
31 |
43 |
44 |
45 | @foreach ($products as $product)
46 |
47 |
62 |
63 | @endforeach
64 |
65 |
66 | {{ $products->appends(request()->input())->links() }}
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | @endsection
76 |
--------------------------------------------------------------------------------
/resources/views/welcome.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 | @section('title', 'Welcome')
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 | Welcome to the site Welcome to the site
11 |
12 |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquam, assumenda. Culpa, libero.
13 |
Shop
14 |
Contact Us
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
Ecommerce
23 |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam accusamus eos quibusdam, esse voluptates voluptatibus id corporis facere neque amet alias molestias itaque ex porro architecto blanditiis distinctio maxime laboriosam.
24 |
25 |
26 |
27 |
28 | @foreach ($products as $product)
29 |
30 |
45 |
46 | @endforeach
47 |
48 |
49 |
54 |
55 |
56 |
57 |
58 | @foreach ($hotProducts as $product)
59 |
60 |
75 |
76 | @endforeach
77 |
78 |
79 |
80 |
81 |
82 | @endsection
83 |
--------------------------------------------------------------------------------