├── tests ├── Unit │ ├── .gitignore │ ├── Roles │ │ └── RoleUnitTest.php │ ├── Employees │ │ └── EmployeeUnitTest.php │ ├── Checkout │ │ └── CheckoutUnitTest.php │ ├── AttributeValues │ │ └── AttributeValueUnitTest.php │ └── Cities │ │ └── CityUnitTest.php ├── CreatesApplication.php └── Feature │ ├── Front │ ├── Checkout │ │ └── CheckoutFeatureTest.php │ ├── Categories │ │ └── FrontCategoryFeatureTest.php │ └── Home │ │ └── HomeFeatureTest.php │ └── Admin │ └── Dashboard │ └── DashboardFeatureTest.php ├── database ├── .gitignore ├── seeds │ ├── OrderTableSeeder.php │ ├── ProductsTableSeeder.php │ ├── CustomersTableSeeder.php │ ├── CourierTableSeeder.php │ ├── CategoriesTableSeeder.php │ ├── CustomerAddressesTableSeeder.php │ ├── EmployeesTableSeeder.php │ ├── OrderStatusTableSeeder.php │ ├── DatabaseSeeder.php │ └── CategoryProductsTableSeeder.php ├── factories │ ├── AttributeModelFactory.php │ ├── ProductAttributeModelFactory.php │ ├── RoleModelFactory.php │ ├── OrderStatusModelFactory.php │ ├── PermissionModelFactory.php │ ├── CityModelFactory.php │ ├── CourierModelFactory.php │ ├── ProvinceModelFactory.php │ ├── CustomerModelFactory.php │ ├── EmployeeModelFactory.php │ ├── CountryModelFactory.php │ ├── AddressModelFactory.php │ ├── ProductModelFactory.php │ ├── OrderModelFactory.php │ └── CategoryModelFactory.php └── migrations │ ├── 2018_03_10_110530_create_attributes_table.php │ ├── 2018_02_19_151228_create_cost_column.php │ ├── 2017_06_17_011245_create_shoppingcart_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2017_06_12_225546_create_order_status_table.php │ ├── 2016_05_26_051502_create_cities_table.php │ ├── 2018_01_18_163143_create_product_images_table.php │ ├── 2016_05_26_035202_create_provinces_table.php │ ├── 2018_03_10_150920_create_attribute_values_table.php │ ├── 2017_06_13_005248_create_payment_methods.php │ ├── 2017_06_13_044714_create_couriers_table.php │ ├── 2016_05_26_020731_create_country_table.php │ ├── 2018_03_11_014046_create_product_attributes_table.php │ ├── 2014_10_12_000000_create_customers_table.php │ ├── 2014_10_12_000010_create_employees_table.php │ ├── 2017_06_11_033553_create_category_product_table.php │ ├── 2017_06_13_091740_create_order_products_table.php │ ├── 2017_06_11_015526_create_categories_table.php │ ├── 2018_03_11_090249_create_attribute_value_product_attribute_table.php │ ├── 2017_06_10_225235_create_products_table.php │ └── 2017_06_11_073305_create_address_table.php ├── resources ├── views │ ├── invoices │ │ └── .gitkeep │ ├── front │ │ ├── shared │ │ │ └── sidebar.blade.php │ │ ├── checkout-success.blade.php │ │ ├── checkout-cancel.blade.php │ │ ├── categories │ │ │ └── sidebar-category.blade.php │ │ └── products │ │ │ ├── product-search.blade.php │ │ │ └── product.blade.php │ ├── admin │ │ ├── shared │ │ │ ├── status-select.blade.php │ │ │ ├── category-children.blade.php │ │ │ ├── cities.blade.php │ │ │ ├── categories.blade.php │ │ │ └── provinces.blade.php │ │ ├── products │ │ │ └── list.blade.php │ │ ├── dashboard.blade.php │ │ ├── employees │ │ │ └── show.blade.php │ │ ├── provinces │ │ │ └── edit.blade.php │ │ ├── cities │ │ │ └── edit.blade.php │ │ └── attributes │ │ │ └── create.blade.php │ ├── emails │ │ └── inquiry │ │ │ └── send.blade.php │ └── layouts │ │ ├── admin │ │ └── footer.blade.php │ │ ├── front │ │ ├── category-sidebar-sub.blade.php │ │ ├── category-nav.blade.php │ │ ├── category-sub.blade.php │ │ ├── home-slider.blade.php │ │ └── footer.blade.php │ │ ├── status.blade.php │ │ ├── search.blade.php │ │ ├── errors-and-messages.blade.php │ │ └── errors │ │ ├── 403.blade.php │ │ └── 503.blade.php ├── assets │ ├── images │ │ └── banner.jpg │ ├── admin-lte │ │ └── img │ │ │ ├── icons.png │ │ │ ├── avatar.png │ │ │ ├── avatar2.png │ │ │ ├── avatar3.png │ │ │ ├── avatar5.png │ │ │ ├── photo1.png │ │ │ ├── photo2.png │ │ │ ├── photo3.jpg │ │ │ ├── photo4.jpg │ │ │ ├── avatar04.png │ │ │ ├── boxed-bg.jpg │ │ │ ├── boxed-bg.png │ │ │ ├── credit │ │ │ ├── visa.png │ │ │ ├── cirrus.png │ │ │ ├── mestro.png │ │ │ ├── paypal.png │ │ │ ├── paypal2.png │ │ │ ├── mastercard.png │ │ │ └── american-express.png │ │ │ ├── default-50x50.gif │ │ │ ├── user1-128x128.jpg │ │ │ ├── user2-160x160.jpg │ │ │ ├── user3-128x128.jpg │ │ │ ├── user4-128x128.jpg │ │ │ ├── user5-128x128.jpg │ │ │ ├── user6-128x128.jpg │ │ │ ├── user7-128x128.jpg │ │ │ └── user8-128x128.jpg │ ├── sass │ │ ├── app.scss │ │ └── _variables.scss │ ├── css │ │ └── admin.css │ └── js │ │ ├── custom.js │ │ └── scripts.js └── lang │ └── en │ ├── pagination.php │ ├── auth.php │ └── passwords.php ├── _config.yml ├── bootstrap ├── cache │ └── .gitignore └── autoload.php ├── storage ├── logs │ └── .gitignore ├── app │ ├── public │ │ └── .gitignore │ └── .gitignore └── framework │ ├── cache │ └── .gitignore │ ├── testing │ └── .gitignore │ ├── views │ └── .gitignore │ ├── sessions │ └── .gitignore │ └── .gitignore ├── public ├── robots.txt ├── favicon.ico ├── favicons │ ├── favicon.ico │ ├── apple-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ ├── ms-icon-70x70.png │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── android-icon-144x144.png │ ├── android-icon-192x192.png │ ├── android-icon-36x36.png │ ├── android-icon-48x48.png │ ├── android-icon-72x72.png │ ├── android-icon-96x96.png │ ├── apple-icon-114x114.png │ ├── apple-icon-120x120.png │ ├── apple-icon-144x144.png │ ├── apple-icon-152x152.png │ ├── apple-icon-180x180.png │ ├── apple-icon-precomposed.png │ ├── browserconfig.xml │ └── manifest.json ├── mix-manifest.json └── .htaccess ├── cs-fixer.phar ├── config ├── payees.php ├── stripe.php ├── paypal.php ├── hashing.php ├── view.php └── services.php ├── PULL_REQUEST_TEMPLATE.md ├── .gitattributes ├── app ├── Shop │ ├── Teams │ │ └── Team.php │ ├── Carts │ │ ├── Requests │ │ │ ├── CheckoutInterface.php │ │ │ ├── AddToCartRequest.php │ │ │ ├── StripeExecutionRequest.php │ │ │ ├── CartCheckoutRequest.php │ │ │ └── PayPalCheckoutExecutionRequest.php │ │ ├── Exceptions │ │ │ └── ProductInCartNotFoundException.php │ │ └── Repositories │ │ │ └── Interfaces │ │ │ └── CartRepositoryInterface.php │ ├── Roles │ │ ├── Exceptions │ │ │ └── CreateRoleErrorException.php │ │ ├── Role.php │ │ └── Repositories │ │ │ ├── RoleRepositoryInterface.php │ │ │ └── RoleRepository.php │ ├── Attributes │ │ ├── Exceptions │ │ │ ├── AttributeNotFoundException.php │ │ │ ├── CreateAttributeErrorException.php │ │ │ └── UpdateAttributeErrorException.php │ │ ├── Requests │ │ │ ├── UpdateAttributeRequest.php │ │ │ └── CreateAttributeRequest.php │ │ ├── Attribute.php │ │ └── Repositories │ │ │ └── AttributeRepositoryInterface.php │ ├── Permissions │ │ └── Permission.php │ ├── Customers │ │ ├── Exceptions │ │ │ ├── CreateCustomerInvalidArgumentException.php │ │ │ ├── CustomerPaymentChargingErrorException.php │ │ │ ├── UpdateCutomerInvalidArgumentException.php │ │ │ └── CustomerNotFoundException.php │ │ ├── Transformations │ │ │ └── CustomerTransformable.php │ │ ├── Requests │ │ │ ├── CreateCustomerRequest.php │ │ │ ├── RegisterCustomerRequest.php │ │ │ └── UpdateCustomerRequest.php │ │ ├── Repositories │ │ │ └── Interfaces │ │ │ │ └── CustomerRepositoryInterface.php │ │ └── Customer.php │ ├── PaymentMethods │ │ ├── Stripe │ │ │ └── Exceptions │ │ │ │ └── StripeChargingErrorException.php │ │ ├── Paypal │ │ │ ├── Exceptions │ │ │ │ └── PaypalRequestError.php │ │ │ └── Repositories │ │ │ │ └── PayPalExpressCheckoutRepositoryInterface.php │ │ └── Payment.php │ ├── ProductAttributes │ │ ├── Exceptions │ │ │ └── ProductAttributeNotFoundException.php │ │ ├── Repositories │ │ │ ├── ProductAttributeRepositoryInterface.php │ │ │ └── ProductAttributeRepository.php │ │ └── ProductAttribute.php │ ├── Orders │ │ ├── Exceptions │ │ │ ├── OrderInvalidArgumentException.php │ │ │ └── OrderNotFoundException.php │ │ ├── Repositories │ │ │ └── Interfaces │ │ │ │ └── OrderRepositoryInterface.php │ │ └── Transformers │ │ │ └── OrderTransformable.php │ ├── Addresses │ │ ├── Exceptions │ │ │ ├── AddressInvalidArgumentException.php │ │ │ └── AddressNotFoundException.php │ │ ├── Requests │ │ │ ├── CreateAddressRequest.php │ │ │ └── UpdateAddressRequest.php │ │ └── Repositories │ │ │ └── Interfaces │ │ │ └── AddressRepositoryInterface.php │ ├── Countries │ │ ├── Exceptions │ │ │ ├── CountryInvalidArgumentException.php │ │ │ └── CountryNotFoundException.php │ │ ├── Repositories │ │ │ └── Interfaces │ │ │ │ └── CountryRepositoryInterface.php │ │ └── Country.php │ ├── Couriers │ │ ├── Exceptions │ │ │ ├── CourierInvalidArgumentException.php │ │ │ └── CourierNotFoundException.php │ │ ├── Requests │ │ │ ├── CreateCourierRequest.php │ │ │ └── UpdateCourierRequest.php │ │ ├── Courier.php │ │ └── Repositories │ │ │ └── Interfaces │ │ │ └── CourierRepositoryInterface.php │ ├── Products │ │ ├── Exceptions │ │ │ ├── ProductInvalidArgumentException.php │ │ │ └── ProductNotFoundException.php │ │ ├── Requests │ │ │ ├── UpdateProductRequest.php │ │ │ └── CreateProductRequest.php │ │ └── Transformations │ │ │ └── ProductTransformable.php │ ├── Categories │ │ ├── Exceptions │ │ │ ├── CategoryInvalidArgumentException.php │ │ │ └── CategoryNotFoundException.php │ │ ├── Category.php │ │ └── Repositories │ │ │ └── Interfaces │ │ │ └── CategoryRepositoryInterface.php │ ├── OrderProducts │ │ ├── Exceptions │ │ │ └── OrderDetailInvalidArgumentException.php │ │ ├── OrderProduct.php │ │ └── Repositories │ │ │ └── Interfaces │ │ │ └── OrderProductRepositoryInterface.php │ ├── OrderStatuses │ │ ├── Exceptions │ │ │ ├── OrderStatusInvalidArgumentException.php │ │ │ └── OrderStatusNotFoundException.php │ │ ├── Requests │ │ │ ├── CreateOrderStatusRequest.php │ │ │ └── UpdateOrderStatusRequest.php │ │ ├── OrderStatus.php │ │ └── Repositories │ │ │ └── Interfaces │ │ │ └── OrderStatusRepositoryInterface.php │ ├── Base │ │ ├── BaseFormRequest.php │ │ └── Interfaces │ │ │ └── BaseRepositoryInterface.php │ ├── Cities │ │ ├── Exceptions │ │ │ └── CityNotFoundException.php │ │ ├── Repositories │ │ │ ├── Interfaces │ │ │ │ └── CityRepositoryInterface.php │ │ │ └── CityRepository.php │ │ ├── Requests │ │ │ └── UpdateCityRequest.php │ │ └── City.php │ ├── Provinces │ │ ├── Exceptions │ │ │ └── ProvinceNotFoundException.php │ │ ├── Repositories │ │ │ └── Interfaces │ │ │ │ └── ProvinceRepositoryInterface.php │ │ └── Province.php │ ├── Employees │ │ ├── Exceptions │ │ │ └── EmployeeNotFoundException.php │ │ ├── Requests │ │ │ ├── LoginRequest.php │ │ │ ├── CreateEmployeeRequest.php │ │ │ └── UpdateEmployeeRequest.php │ │ ├── Repositories │ │ │ └── Interfaces │ │ │ │ └── EmployeeRepositoryInterface.php │ │ └── Employee.php │ ├── AttributeValues │ │ ├── Requests │ │ │ └── CreateAttributeValueRequest.php │ │ ├── Repositories │ │ │ └── AttributeValueRepositoryInterface.php │ │ └── AttributeValue.php │ ├── ProductImages │ │ ├── ProductImage.php │ │ └── ProductImageRepository.php │ ├── Tools │ │ └── UploadableTrait.php │ └── Checkout │ │ └── CheckoutRepository.php ├── Http │ ├── Controllers │ │ ├── Admin │ │ │ ├── DashboardController.php │ │ │ ├── Categories │ │ │ │ └── Requests │ │ │ │ │ ├── CreateCategoryRequest.php │ │ │ │ │ └── UpdateCategoryRequest.php │ │ │ └── Countries │ │ │ │ └── Requests │ │ │ │ └── UpdateCountryRequest.php │ │ ├── Controller.php │ │ ├── Auth │ │ │ ├── ForgotPasswordController.php │ │ │ └── ResetPasswordController.php │ │ └── Front │ │ │ ├── CategoryController.php │ │ │ └── HomeController.php │ └── Middleware │ │ ├── EncryptCookies.php │ │ ├── VerifyCsrfToken.php │ │ ├── TrimStrings.php │ │ ├── TrustProxies.php │ │ ├── RedirectIfAuthenticated.php │ │ └── RedirectIfNotAdmin.php ├── Providers │ ├── BroadcastServiceProvider.php │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ └── EventServiceProvider.php ├── Listeners │ └── OrderCreateEventListener.php ├── Console │ └── Kernel.php ├── Events │ └── OrderCreateEvent.php └── Mail │ ├── SendOrderToCustomerMailable.php │ └── sendEmailNotificationToAdminMailable.php ├── .travis.yml ├── CONTRIBUTING.md ├── changelog.md ├── .gitignore ├── routes ├── channels.php ├── console.php └── api.php ├── server.php ├── bitbucket-pipelines.yml ├── .env.testing ├── LICENSE.md ├── package.json ├── .env.example └── phpunit.xml /tests/Unit/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /resources/views/invoices/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /cs-fixer.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/cs-fixer.phar -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicon.ico -------------------------------------------------------------------------------- /config/payees.php: -------------------------------------------------------------------------------- 1 | env('PAYMENT_METHODS', 'paypal') 5 | ]; -------------------------------------------------------------------------------- /public/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/favicon.ico -------------------------------------------------------------------------------- /public/favicons/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon.png -------------------------------------------------------------------------------- /public/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/favicon-96x96.png -------------------------------------------------------------------------------- /public/favicons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/ms-icon-144x144.png -------------------------------------------------------------------------------- /public/favicons/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/ms-icon-150x150.png -------------------------------------------------------------------------------- /public/favicons/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/ms-icon-310x310.png -------------------------------------------------------------------------------- /public/favicons/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/ms-icon-70x70.png -------------------------------------------------------------------------------- /resources/assets/images/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/images/banner.jpg -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Title of the PR 2 | 3 | ## Description of the PR with the link on the issue trying to solve 4 | -------------------------------------------------------------------------------- /public/favicons/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-57x57.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-60x60.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-72x72.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-76x76.png -------------------------------------------------------------------------------- /public/favicons/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/android-icon-144x144.png -------------------------------------------------------------------------------- /public/favicons/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/android-icon-192x192.png -------------------------------------------------------------------------------- /public/favicons/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/android-icon-36x36.png -------------------------------------------------------------------------------- /public/favicons/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/android-icon-48x48.png -------------------------------------------------------------------------------- /public/favicons/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/android-icon-72x72.png -------------------------------------------------------------------------------- /public/favicons/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/android-icon-96x96.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-114x114.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-120x120.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-144x144.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-152x152.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-180x180.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/icons.png -------------------------------------------------------------------------------- /public/favicons/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/public/favicons/apple-icon-precomposed.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/avatar.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/avatar2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/avatar2.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/avatar3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/avatar3.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/avatar5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/avatar5.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/photo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/photo1.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/photo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/photo2.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/photo3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/photo3.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/photo4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/photo4.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/avatar04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/avatar04.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/boxed-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/boxed-bg.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/boxed-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/boxed-bg.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/credit/visa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/credit/visa.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/credit/cirrus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/credit/cirrus.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/credit/mestro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/credit/mestro.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/credit/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/credit/paypal.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/credit/paypal2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/credit/paypal2.png -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/default-50x50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/default-50x50.gif -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/user1-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/user1-128x128.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/user2-160x160.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/user2-160x160.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/user3-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/user3-128x128.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/user4-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/user4-128x128.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/user5-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/user5-128x128.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/user6-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/user6-128x128.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/user7-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/user7-128x128.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/user8-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/user8-128x128.jpg -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/credit/mastercard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/credit/mastercard.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /resources/assets/admin-lte/img/credit/american-express.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fg/laracom/master/resources/assets/admin-lte/img/credit/american-express.png -------------------------------------------------------------------------------- /app/Shop/Teams/Team.php: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /app/Shop/Carts/Requests/CheckoutInterface.php: -------------------------------------------------------------------------------- 1 | create(); 11 | } 12 | } -------------------------------------------------------------------------------- /resources/assets/sass/app.scss: -------------------------------------------------------------------------------- 1 | 2 | // Fonts 3 | @import url("https://fonts.googleapis.com/css?family=Raleway:300,400,600"); 4 | 5 | // Variables 6 | @import "variables"; 7 | 8 | // Bootstrap 9 | @import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap"; 10 | -------------------------------------------------------------------------------- /app/Shop/Orders/Exceptions/OrderInvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | create(); 11 | } 12 | } -------------------------------------------------------------------------------- /app/Shop/Addresses/Exceptions/AddressInvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | create(); 11 | } 12 | } -------------------------------------------------------------------------------- /app/Shop/Categories/Exceptions/CategoryInvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /public/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/css/admin.min.css": "/css/admin.min.css", 3 | "/css/style.min.css": "/css/style.min.css", 4 | "/js/admin.min.js": "/js/admin.min.js", 5 | "/js/front.min.js": "/js/front.min.js", 6 | "/js/scripts.js": "/js/scripts.js", 7 | "/js/custom.js": "/js/custom.js" 8 | } -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/DashboardController.php: -------------------------------------------------------------------------------- 1 | Status 2 | -------------------------------------------------------------------------------- /resources/views/emails/inquiry/send.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | 3 | # Inquiry Message from the website 4 | 5 | ## Name : {{ $from }} 6 | 7 | ## Email : {{ $email }} 8 | 9 | ## Person type : {{ $iam }} 10 | 11 | ## Message : {{ $message }} 12 | 13 | Thanks,
14 | {{ config('app.name') }} Team 15 | @endcomponent 16 | -------------------------------------------------------------------------------- /resources/views/layouts/admin/footer.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Shop/Roles/Repositories/RoleRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | create([ 11 | 'name' => 'Free Shipping', 12 | 'description' => 'Free Shipping' 13 | ]); 14 | } 15 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.1 5 | 6 | sudo: false 7 | 8 | cache: 9 | directories: 10 | - $HOME/.composer/cache 11 | 12 | before_script: 13 | - cp .env.testing .env 14 | - composer install --no-interaction 15 | - composer dump-autoload 16 | 17 | script: 18 | - vendor/bin/phpunit --coverage-clover=coverage.xml 19 | after_success: 20 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | slug) }}">{{ $category->name }} 3 | 6 | @endforeach -------------------------------------------------------------------------------- /app/Shop/Base/BaseFormRequest.php: -------------------------------------------------------------------------------- 1 | create([ 11 | 'name' => 'Uncategorized', 12 | 'slug' => 'uncategorized', 13 | 'parent_id' => 0 14 | ]); 15 | } 16 | } -------------------------------------------------------------------------------- /app/Shop/Attributes/Requests/UpdateAttributeRequest.php: -------------------------------------------------------------------------------- 1 | 'stripe', 4 | 'description' => 'The new standard in online payments', 5 | 'key' => env('STRIPE_KEY', 'xxx'), 6 | 'secret' => env('STRIPE_SECRET', 'xxx'), 7 | 'redirect_url' => env('STRIPE_REDIRECT_URL', 'xxxx'), 8 | 'cancel_url' => env('STRIPE_CANCEL_URL', 'xxxx'), 9 | 'failed_url' => env('STRIPE_FAILED_URL', 'xxxx'), 10 | ]; -------------------------------------------------------------------------------- /app/Shop/Cities/Exceptions/CityNotFoundException.php: -------------------------------------------------------------------------------- 1 | 5 |
6 |
7 |
8 |

Your order is under way! Show more!

9 |
10 |
11 | 12 | @endsection -------------------------------------------------------------------------------- /resources/views/layouts/status.blade.php: -------------------------------------------------------------------------------- 1 | @if(isset($status)) 2 | @if($status == 1) 3 | 1 4 | 5 | @else 6 | 0 7 | 8 | @endif 9 | @endif -------------------------------------------------------------------------------- /app/Shop/Countries/Exceptions/CountryNotFoundException.php: -------------------------------------------------------------------------------- 1 | 5 |
6 |
7 |
8 |

You have cancelled your order. Maybe you want to checkout other items?

9 |
10 |
11 | 12 | @endsection -------------------------------------------------------------------------------- /app/Shop/Attributes/Requests/CreateAttributeRequest.php: -------------------------------------------------------------------------------- 1 | ['required'] 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Shop/Carts/Exceptions/ProductInCartNotFoundException.php: -------------------------------------------------------------------------------- 1 | hasMany(AttributeValue::class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Sept-17-2017 2 | 3 | ## Features 4 | 5 | - Invoice on the order can be generated / downloaded as PDF 6 | - Create email notifications 7 | - Products search 8 | - Order search 9 | - Customer search 10 | - Customer address search 11 | - Transform the order with readable values 12 | - Add the newsletter feature 13 | 14 | ## Bugs 15 | 16 | - Redirect to `/admin` when already logged in 17 | - Provinces / Cities API fix 18 | - Reset password link fix 19 | - Dynamic selection of cities in frontend -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /public/hot 3 | /public/storage 4 | /public/fonts 5 | /public/img 6 | /public/images 7 | /public/fonts/vendor 8 | /public/css/app.css 9 | /public/js/app.js 10 | /storage/*.key 11 | /vendor 12 | /.idea 13 | /.vagrant 14 | Homestead.json 15 | Homestead.yaml 16 | npm-debug.log 17 | yarn-error.log 18 | .env 19 | .DS_Store 20 | /public/.DS_Store 21 | yarn.lock 22 | /build 23 | Envoy.blade.php 24 | /coverage 25 | storage/app/public/storage 26 | \.php_cs\.cache 27 | public/css 28 | public/js -------------------------------------------------------------------------------- /app/Shop/AttributeValues/Requests/CreateAttributeValueRequest.php: -------------------------------------------------------------------------------- 1 | ['required'] 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Shop/OrderStatuses/Requests/CreateOrderStatusRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'unique:order_statuses'] 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /resources/views/front/categories/sidebar-category.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/Categories/Requests/CreateCategoryRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'unique:categories'] 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Shop/Carts/Requests/AddToCartRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'integer'], 18 | 'quantity' => ['required'] 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Shop/Addresses/Requests/CreateAddressRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 18 | 'address_1' => ['required'] 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Shop/Addresses/Requests/UpdateAddressRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 18 | 'address_1' => ['required'] 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Shop/PaymentMethods/Payment.php: -------------------------------------------------------------------------------- 1 | payment = $class; 19 | } 20 | 21 | /** 22 | * @return mixed 23 | */ 24 | public function init() 25 | { 26 | return $this->payment; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | user(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Shop/Couriers/Requests/CreateCourierRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'unique:couriers'], 18 | 'cost' => ['required_if:is_free,0'] 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Shop/Customers/Transformations/CustomerTransformable.php: -------------------------------------------------------------------------------- 1 | id = (int) $customer->id; 13 | $prop->name = $customer->name; 14 | $prop->email = $customer->email; 15 | $prop->status = (int) $customer->status; 16 | 17 | return $prop; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /database/seeds/CustomerAddressesTableSeeder.php: -------------------------------------------------------------------------------- 1 | create()->each(function ($customer) { 12 | factory(Address::class, 3)->make()->each(function($address) use ($customer) { 13 | $customer->addresses()->save($address); 14 | }); 15 | }); 16 | } 17 | } -------------------------------------------------------------------------------- /app/Shop/Cities/Requests/UpdateCityRequest.php: -------------------------------------------------------------------------------- 1 | ['required', Rule::unique('cities')->ignore(request()->segment(7))] 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /resources/assets/css/admin.css: -------------------------------------------------------------------------------- 1 | #search-btn { 2 | border: 1px solid #d2d6de; 3 | } 4 | #search-btn:hover { 5 | background: #605ca8; 6 | color: #eee; 7 | } 8 | .tab-content > .tab-pane { 9 | border: 1px solid #ddd; 10 | padding: 15px; 11 | border-top: none; 12 | } 13 | #search-btn { 14 | border: 1px solid #bbb; 15 | } 16 | #admin-search { 17 | margin-bottom: 15px; 18 | } 19 | table.dataTable thead td, 20 | table.dataTable tfoot td, 21 | table.dataTable.no-footer, 22 | table.dataTable thead th { 23 | border-bottom: none; 24 | } -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | ['required', Rule::unique('couriers')->ignore($this->segment(3))] 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Shop/ProductImages/ProductImage.php: -------------------------------------------------------------------------------- 1 | belongsTo(Product::class); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/views/layouts/front/category-nav.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Unit/Roles/RoleUnitTest.php: -------------------------------------------------------------------------------- 1 | expectException(CreateRoleErrorException::class); 16 | 17 | $roleRepo = new RoleRepository(new Role()); 18 | $roleRepo->createRole([]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | guard($guard)->check(); 20 | 21 | return $next($request); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Shop/OrderProducts/OrderProduct.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 16 | }); 17 | -------------------------------------------------------------------------------- /app/Shop/OrderProducts/Repositories/Interfaces/OrderProductRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | ['required', Rule::unique('order_statuses')->ignore($this->segment('4'))] 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /config/paypal.php: -------------------------------------------------------------------------------- 1 | 'paypal', 5 | 'description' => 'PayPal - Safe, Secured and Easy to pay online!', 6 | 'account_id' => env('PP_ACCOUNT_ID', 'xxxx'), 7 | 'client_id' => env('PP_CLIENT_ID', 'xxxx'), 8 | 'client_secret' => env('PP_CLIENT_SECRET', 'xxxx'), 9 | 'api_url' => env('PP_API_URL', 'https://api.sandbox.paypal.com'), 10 | 'redirect_url' => env('PP_REDIRECT_URL', 'xxxx'), 11 | 'cancel_url' => env('PP_CANCEL_URL', 'xxxx'), 12 | 'failed_url' => env('PP_FAILED_URL', 'xxxx'), 13 | 'mode' => env('PP_MODE', 'xxxx') 14 | ]; -------------------------------------------------------------------------------- /resources/views/layouts/search.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 11 | 12 |
-------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 20 | 21 | Hash::driver('bcrypt')->setRounds(4); 22 | 23 | return $app; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /database/seeds/EmployeesTableSeeder.php: -------------------------------------------------------------------------------- 1 | create()->each(function (Employee $employee) { 12 | factory(Role::class)->create(['name' => 'admin'])->each(function(Role $role) use ($employee) { 13 | $employee->roles()->save($role); 14 | }); 15 | }); 16 | 17 | factory(Employee::class)->create(); 18 | } 19 | } -------------------------------------------------------------------------------- /app/Shop/Carts/Requests/StripeExecutionRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 18 | 'courier' => ['required'], 19 | 'billing_address' => ['required'], 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Shop/Customers/Requests/CreateCustomerRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 18 | 'email' => ['required', 'email', 'unique:customers'], 19 | 'password' => ['required', 'min:8'] 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /resources/views/layouts/front/category-sub.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | ]; 21 | -------------------------------------------------------------------------------- /resources/assets/js/custom.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $("#brand-logo").owlCarousel({ 3 | autoPlay: 3000, //Set AutoPlay to 3 seconds 4 | items: 6, 5 | itemsDesktop: [1199, 6], 6 | itemsDesktopSmall: [979, 6] 7 | }); 8 | 9 | $('.select2').select2(); 10 | 11 | if ($('#thumbnails li img').length > 0) { 12 | $('#thumbnails li img').on('click', function () { 13 | $('#main-image') 14 | .attr('src', $(this).attr('src') +'?w=400') 15 | .attr('data-zoom', $(this).attr('src') +'?w=1200'); 16 | }); 17 | } 18 | }); -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | ['required'], 23 | 'billing_address' => ['required'] 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Shop/Customers/Requests/RegisterCustomerRequest.php: -------------------------------------------------------------------------------- 1 | 'required|string|max:255', 18 | 'email' => 'required|string|email|max:255|unique:customers', 19 | 'password' => 'required|string|min:6|confirmed', 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /bootstrap/autoload.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes If Not A Folder... 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | RewriteRule ^(.*)/$ /$1 [L,R=301] 11 | 12 | # Handle Front Controller... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_FILENAME} !-f 15 | RewriteRule ^ index.php [L] 16 | 17 | # Handle Authorization Header 18 | RewriteCond %{HTTP:Authorization} . 19 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 20 | 21 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | get('/user', function (Request $request) { 18 | return $request->user(); 19 | }); 20 | -------------------------------------------------------------------------------- /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/Shop/Couriers/Repositories/Interfaces/CourierRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | belongsTo(Province::class); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Shop/OrderStatuses/OrderStatus.php: -------------------------------------------------------------------------------- 1 | hasMany(Order::class); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /resources/views/front/products/product-search.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.front.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |

Search Results

9 |
10 |
11 |
12 |
13 | @include('front.categories.sidebar-category') 14 |
15 |
16 |
17 | @include('front.products.product-list', ['products' => $products]) 18 |
19 |
20 |
21 | @endsection -------------------------------------------------------------------------------- /app/Shop/Products/Requests/UpdateProductRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 19 | 'name' => ['required', Rule::unique('products')->ignore($this->segment(3))], 20 | 'quantity' => ['required', 'integer'], 21 | 'price' => ['required'] 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/views/admin/shared/category-children.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Shop/Carts/Requests/PayPalCheckoutExecutionRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 18 | 'PayerID' => ['required'], 19 | 'courier' => ['required'], 20 | 'billing_address' => ['required'], 21 | 'payment' => ['required'] 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Shop/Products/Requests/CreateProductRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 18 | 'name' => ['required', 'unique:products'], 19 | 'quantity' => ['required', 'numeric'], 20 | 'price' => ['required'], 21 | 'cover' => ['required', 'file', 'image:png,jpeg,jpg,gif'] 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Shop/ProductImages/ProductImageRepository.php: -------------------------------------------------------------------------------- 1 | model = $productImage; 18 | } 19 | 20 | /** 21 | * @return mixed 22 | */ 23 | public function findProduct() : Product 24 | { 25 | return $this->model->product; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /resources/views/admin/shared/cities.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | @foreach($cities as $city) 10 | 11 | 12 | 17 | 18 | @endforeach 19 | 20 |
NameActions
{{ $city['name'] }} 13 |
14 | Edit 15 |
16 |
-------------------------------------------------------------------------------- /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/Shop/Countries/Repositories/Interfaces/CountryRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | ['required', 'email'], 28 | 'password' => ['required'] 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Shop/AttributeValues/Repositories/AttributeValueRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | define(Attribute::class, function (Faker\Generator $faker) { 17 | return [ 18 | 'name' => $faker->unique()->word 19 | ]; 20 | }); 21 | -------------------------------------------------------------------------------- /app/Shop/Countries/Country.php: -------------------------------------------------------------------------------- 1 | hasMany(Province::class); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfNotAdmin.php: -------------------------------------------------------------------------------- 1 | guard($guard)->check()) { 21 | $request->session()->flash('error', 'You must be an employee to see this page'); 22 | return redirect(route('admin.login')); 23 | } 24 | 25 | return $next($request); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Shop/Base/Interfaces/BaseRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 18 | ]; 19 | 20 | /** 21 | * Register any authentication / authorization services. 22 | * 23 | * @return void 24 | */ 25 | public function boot() 26 | { 27 | $this->registerPolicies(); 28 | 29 | // 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Shop/Tools/UploadableTrait.php: -------------------------------------------------------------------------------- 1 | storeAs( 23 | $folder, 24 | $name . "." . $file->getClientOriginalExtension(), 25 | $disk 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Providers/EventServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'App\Listeners\OrderCreateEventListener', 18 | ], 19 | ]; 20 | 21 | /** 22 | * Register any events for your application. 23 | * 24 | * @return void 25 | */ 26 | public function boot() 27 | { 28 | parent::boot(); 29 | 30 | // 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/factories/ProductAttributeModelFactory.php: -------------------------------------------------------------------------------- 1 | define(ProductAttribute::class, function (Faker\Generator $faker) { 18 | return [ 19 | 'quantity' => 1, 20 | 'price' => 1.55 21 | ]; 22 | }); 23 | -------------------------------------------------------------------------------- /database/factories/RoleModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Role::class, function (Faker\Generator $faker) { 18 | 19 | return [ 20 | 'name' => $faker->word, 21 | 'display_name' => '', 22 | 'description' => '' 23 | ]; 24 | }); 25 | -------------------------------------------------------------------------------- /resources/views/admin/products/list.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.admin.app') 2 | 3 | @section('content') 4 | 5 |
6 | @include('layouts.errors-and-messages') 7 | 8 | @if($products) 9 |
10 |
11 |

Products

12 | @include('layouts.search', ['route' => route('admin.products.index')]) 13 | @include('admin.shared.products') 14 | {{ $products->links() }} 15 |
16 | 17 |
18 | 19 | @endif 20 |
21 | 22 | @endsection 23 | -------------------------------------------------------------------------------- /database/factories/OrderStatusModelFactory.php: -------------------------------------------------------------------------------- 1 | define(OrderStatus::class, function (Faker\Generator $faker) { 18 | 19 | return [ 20 | 'name' => $faker->word, 21 | 'color' => $faker->hexColor 22 | ]; 23 | }); 24 | -------------------------------------------------------------------------------- /app/Shop/AttributeValues/AttributeValue.php: -------------------------------------------------------------------------------- 1 | belongsTo(Attribute::class); 21 | } 22 | 23 | /** 24 | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 25 | */ 26 | public function productAttributes() 27 | { 28 | return $this->belongsToMany(ProductAttribute::class); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Shop/OrderStatuses/Repositories/Interfaces/OrderStatusRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | create([ 11 | 'name' => 'paid', 12 | 'color' => 'green' 13 | ]); 14 | 15 | factory(OrderStatus::class)->create([ 16 | 'name' => 'pending', 17 | 'color' => 'yellow' 18 | ]); 19 | 20 | factory(OrderStatus::class)->create([ 21 | 'name' => 'error', 22 | 'color' => 'red' 23 | ]); 24 | 25 | factory(OrderStatus::class)->create([ 26 | 'name' => 'on-delivery', 27 | 'color' => 'blue' 28 | ]); 29 | } 30 | } -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/Categories/Requests/UpdateCategoryRequest.php: -------------------------------------------------------------------------------- 1 | ['required', Rule::unique('categories')->ignore(request()->segment(3))] 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Shop/ProductAttributes/ProductAttribute.php: -------------------------------------------------------------------------------- 1 | belongsTo(Product::class); 22 | } 23 | 24 | /** 25 | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 26 | */ 27 | public function attributesValues() 28 | { 29 | return $this->belongsToMany(AttributeValue::class); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/factories/PermissionModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Permission::class, function (Faker\Generator $faker) { 18 | 19 | return [ 20 | 'name' => $faker->word, 21 | 'display_name' => '', 22 | 'description' => '' 23 | ]; 24 | }); 25 | -------------------------------------------------------------------------------- /app/Shop/Employees/Requests/CreateEmployeeRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 28 | 'email' => ['required', 'email', 'unique:employees'], 29 | 'password' => ['required', 'min:8'] 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Shop/Provinces/Province.php: -------------------------------------------------------------------------------- 1 | belongsTo(Country::class); 31 | } 32 | 33 | public function cities() 34 | { 35 | return $this->hasMany(City::class); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /bitbucket-pipelines.yml: -------------------------------------------------------------------------------- 1 | # This is a sample build configuration for PHP. 2 | # Check our guides at https://confluence.atlassian.com/x/e8YWN for more examples. 3 | # Only use spaces to indent your .yml configuration. 4 | # ----- 5 | # You can specify a custom docker image from Docker Hub as your build environment. 6 | image: dockette/php71 7 | 8 | pipelines: 9 | default: 10 | - step: 11 | caches: 12 | - composer 13 | - vendor-directory 14 | script: 15 | - apt-get update && apt-get install -y unzip 16 | - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 17 | - composer install 18 | - cp .env.example .env 19 | - vendor/bin/phpunit 20 | definitions: 21 | caches: 22 | vendor-directory: vendor -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/Countries/Requests/UpdateCountryRequest.php: -------------------------------------------------------------------------------- 1 | ['max:2'], 28 | 'iso3' => ['max:3'], 29 | 'numcode' => ['numeric'], 30 | 'phonecode' => ['numeric'] 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Shop/Customers/Requests/UpdateCustomerRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 29 | 'email' => ['required', 'email', Rule::unique('customers')->ignore($this->segment(3))] 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Shop/Employees/Repositories/Interfaces/EmployeeRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name')->unique(); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('attributes'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Shop/Employees/Requests/UpdateEmployeeRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 29 | 'email' => ['required', 'email', Rule::unique('employees', 'email')->ignore($this->segment(3))] 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /resources/views/admin/shared/categories.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Feature/Front/Checkout/CheckoutFeatureTest.php: -------------------------------------------------------------------------------- 1 | actingAs($this->customer, 'web') 14 | ->post(route('checkout.execute', [])) 15 | ->assertStatus(302) 16 | ->assertSessionHasErrors(); 17 | } 18 | 19 | /** @test */ 20 | public function it_fails_validation_in_preparing_payPal_checkout_items() 21 | { 22 | $this 23 | ->actingAs($this->customer, 'web') 24 | ->get(route('checkout.execute', [])) 25 | ->assertStatus(302) 26 | ->assertSessionHasErrors(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/factories/CityModelFactory.php: -------------------------------------------------------------------------------- 1 | define(City::class, function (Faker\Generator $faker) { 19 | 20 | $province = factory(Province::class)->create(); 21 | 22 | return [ 23 | 'name' => $faker->country, 24 | 'province_id' => $province->id 25 | ]; 26 | }); 27 | -------------------------------------------------------------------------------- /database/migrations/2018_02_19_151228_create_cost_column.php: -------------------------------------------------------------------------------- 1 | decimal('cost')->nullable()->default('0.00')->after('is_free'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('couriers', function (Blueprint $table) { 29 | $table->dropColumn(['cost']); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/factories/CourierModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Courier::class, function (Faker\Generator $faker) { 18 | 19 | return [ 20 | 'name' => $faker->company, 21 | 'description' => $faker->paragraph, 22 | 'url' => $faker->url, 23 | 'is_free' => 1, 24 | 'status' => 1 25 | ]; 26 | }); 27 | -------------------------------------------------------------------------------- /database/factories/ProvinceModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Province::class, function (Faker\Generator $faker) { 19 | 20 | $country = factory(Country::class)->create(); 21 | 22 | return [ 23 | 'name' => $faker->country, 24 | 'country_id' => $country->id 25 | ]; 26 | }); 27 | -------------------------------------------------------------------------------- /database/migrations/2017_06_17_011245_create_shoppingcart_table.php: -------------------------------------------------------------------------------- 1 | string('identifier'); 16 | $table->string('instance'); 17 | $table->longText('content'); 18 | $table->nullableTimestamps(); 19 | 20 | $table->primary(['identifier', 'instance']); 21 | }); 22 | } 23 | /** 24 | * Reverse the migrations. 25 | */ 26 | public function down() 27 | { 28 | Schema::drop('shoppingcart'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_06_12_225546_create_order_status_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('color')->nullable(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('order_statuses'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwords must be at least six characters and match the confirmation.', 17 | 'reset' => 'Your password has been reset!', 18 | 'sent' => 'We have e-mailed your password reset link!', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that e-mail address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /app/Shop/Employees/Employee.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name'); 18 | $table->integer('province_id')->unsigned()->index(); 19 | $table->foreign('province_id')->references('id')->on('provinces'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('cities'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /public/favicons/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "App", 3 | "icons": [ 4 | { 5 | "src": "\/android-icon-36x36.png", 6 | "sizes": "36x36", 7 | "type": "image\/png", 8 | "density": "0.75" 9 | }, 10 | { 11 | "src": "\/android-icon-48x48.png", 12 | "sizes": "48x48", 13 | "type": "image\/png", 14 | "density": "1.0" 15 | }, 16 | { 17 | "src": "\/android-icon-72x72.png", 18 | "sizes": "72x72", 19 | "type": "image\/png", 20 | "density": "1.5" 21 | }, 22 | { 23 | "src": "\/android-icon-96x96.png", 24 | "sizes": "96x96", 25 | "type": "image\/png", 26 | "density": "2.0" 27 | }, 28 | { 29 | "src": "\/android-icon-144x144.png", 30 | "sizes": "144x144", 31 | "type": "image\/png", 32 | "density": "3.0" 33 | }, 34 | { 35 | "src": "\/android-icon-192x192.png", 36 | "sizes": "192x192", 37 | "type": "image\/png", 38 | "density": "4.0" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call(EmployeesTableSeeder::class); 15 | $this->call(CustomersTableSeeder::class); 16 | $this->call(ProductsTableSeeder::class); 17 | $this->call(CategoriesTableSeeder::class); 18 | $this->call(CategoryProductsTableSeeder::class); 19 | $this->call(MyCountryTableSeeder::class); 20 | $this->call(MyProvincesTableSeeder::class); 21 | $this->call(MyCitiesTableSeeder::class); 22 | $this->call(CustomerAddressesTableSeeder::class); 23 | $this->call(CourierTableSeeder::class); 24 | $this->call(OrderStatusTableSeeder::class); 25 | $this->call(OrderTableSeeder::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.env.testing: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=testing 3 | APP_KEY=base64:85SiSOVH7/2NVYP5/DBrtBKbL51Nw0+6lF7tx2+jo8o= 4 | APP_DEBUG=true 5 | APP_LOG_LEVEL=debug 6 | APP_URL=http://localhost 7 | 8 | DB_CONNECTION=sqlite 9 | DB_HOST=192.168.10.10 10 | DB_PORT=3306 11 | DB_DATABASE=:memory: 12 | DB_USERNAME=homestead 13 | DB_PASSWORD=secret 14 | 15 | BROADCAST_DRIVER=log 16 | CACHE_DRIVER=file 17 | SESSION_DRIVER=file 18 | QUEUE_DRIVER=sync 19 | 20 | REDIS_HOST=127.0.0.1 21 | REDIS_PASSWORD=null 22 | REDIS_PORT=6379 23 | 24 | MAIL_DRIVER=smtp 25 | MAIL_HOST=smtp.mailtrap.io 26 | MAIL_PORT=2525 27 | MAIL_USERNAME=null 28 | MAIL_PASSWORD=null 29 | MAIL_ENCRYPTION=null 30 | 31 | PUSHER_APP_ID= 32 | PUSHER_APP_KEY= 33 | PUSHER_APP_SECRET= 34 | 35 | PAYPAL_ACCOUNT_ID= 36 | PAYPAL_CLIENT_ID= 37 | PAYPAL_CLIENT_SECRET= 38 | PAYPAL_URL= 39 | PAYPAL_MODE=sandbox 40 | SHIPPING_COST=0 41 | 42 | DEPLOY_SERVER= 43 | INQUIRY_MAIL=your@email.com 44 | 45 | COUNTRY_ID=169 -------------------------------------------------------------------------------- /app/Listeners/OrderCreateEventListener.php: -------------------------------------------------------------------------------- 1 | order); 31 | $orderRepo->sendEmailToCustomer(); 32 | 33 | $orderRepo = new OrderRepository($event->order); 34 | $orderRepo->sendEmailNotificationToAdmin(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Shop/Attributes/Repositories/AttributeRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('product_id')->unsigned()->index(); 19 | $table->foreign('product_id')->references('id')->on('products'); 20 | $table->string('src'); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('product_images'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /resources/views/layouts/front/home-slider.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

{{config('app.name')}} Holiday
Collection

7 |

Download this amazing e-commerce web app for FREE!

8 | DOWNLOAD 9 | Build on DigitalOcean 10 |
11 |
12 |
13 |
14 |
15 |
-------------------------------------------------------------------------------- /database/factories/CustomerModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Customer::class, function (Faker\Generator $faker) { 18 | static $password; 19 | 20 | return [ 21 | 'name' => $faker->firstName, 22 | 'email' => $faker->unique()->safeEmail, 23 | 'password' => $password ?: $password = bcrypt('secret'), 24 | 'remember_token' => str_random(10), 25 | 'status' => 1 26 | ]; 27 | }); 28 | -------------------------------------------------------------------------------- /database/factories/EmployeeModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Employee::class, function (Faker\Generator $faker) { 18 | static $password; 19 | 20 | return [ 21 | 'name' => $faker->firstName, 22 | 'email' => $faker->unique()->safeEmail, 23 | 'password' => $password ?: $password = bcrypt('secret'), 24 | 'remember_token' => str_random(10), 25 | 'status' => 1 26 | ]; 27 | }); 28 | -------------------------------------------------------------------------------- /database/migrations/2016_05_26_035202_create_provinces_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name'); 18 | $table->integer('country_id')->unsigned()->index(); 19 | $table->foreign('country_id')->references('id')->on('countries'); 20 | $table->integer('status')->default(0); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::drop('provinces'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/factories/CountryModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Country::class, function (Faker\Generator $faker) { 18 | 19 | return [ 20 | 'name' => $faker->unique()->country, 21 | 'iso' => $faker->unique()->countryISOAlpha3, 22 | 'iso3' => $faker->unique()->countryISOAlpha3, 23 | 'numcode' => $faker->randomDigit, 24 | 'phonecode' => $faker->randomDigit, 25 | 'status' => 1 26 | ]; 27 | }); 28 | -------------------------------------------------------------------------------- /database/migrations/2018_03_10_150920_create_attribute_values_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('value'); 19 | $table->unsignedInteger('attribute_id'); 20 | $table->foreign('attribute_id')->references('id')->on('attributes'); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('attribute_values'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_06_13_005248_create_payment_methods.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name')->unique(); 19 | $table->string('slug'); 20 | $table->text('description')->nullable(); 21 | $table->string('status')->default(0); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('payment_methods'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire') 28 | // ->hourly(); 29 | } 30 | 31 | /** 32 | * Register the Closure based commands for the application. 33 | * 34 | * @return void 35 | */ 36 | protected function commands() 37 | { 38 | require base_path('routes/console.php'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Shop/Categories/Category.php: -------------------------------------------------------------------------------- 1 | belongsToMany(Product::class); 33 | } 34 | 35 | public function parent() 36 | { 37 | return $this->belongsTo(static::class, 'parent_id'); 38 | } 39 | 40 | public function children() 41 | { 42 | return $this->hasMany(static::class, 'parent_id'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_06_13_044714_create_couriers_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->text('description')->nullable(); 20 | $table->string('url')->nullable(); 21 | $table->integer('is_free'); 22 | $table->integer('status'); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('couriers'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Shop/Products/Transformations/ProductTransformable.php: -------------------------------------------------------------------------------- 1 | exists($product->cover) ? $product->cover : null; 19 | 20 | $prod = new Product; 21 | $prod->id = (int) $product->id; 22 | $prod->name = $product->name; 23 | $prod->sku = $product->sku; 24 | $prod->slug = $product->slug; 25 | $prod->description = $product->description; 26 | $prod->cover = $file; 27 | $prod->quantity = $product->quantity; 28 | $prod->price = $product->price; 29 | $prod->status = $product->status; 30 | 31 | return $prod; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2016_05_26_020731_create_country_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name')->unique(); 18 | $table->string('iso')->unique(); 19 | $table->string('iso3')->nullable(); 20 | $table->integer('numcode')->nullable(); 21 | $table->integer('phonecode'); 22 | $table->integer('status'); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('countries'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Events/OrderCreateEvent.php: -------------------------------------------------------------------------------- 1 | order = $order; 27 | } 28 | 29 | /** 30 | * Get the channels the event should broadcast on. 31 | * 32 | * @return Channel|array 33 | * @codeCoverageIgnore 34 | */ 35 | public function broadcastOn() 36 | { 37 | return new PrivateChannel('channel-name'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/migrations/2018_03_11_014046_create_product_attributes_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('quantity'); 19 | $table->decimal('price')->nullable(); 20 | $table->unsignedInteger('product_id'); 21 | $table->foreign('product_id')->references('id')->on('products'); 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_attributes'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_customers_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('email')->unique(); 20 | $table->string('password'); 21 | $table->integer('status')->default(1); 22 | $table->softDeletes(); 23 | $table->rememberToken(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('customers'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000010_create_employees_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('email')->unique(); 20 | $table->string('password'); 21 | $table->integer('status')->default(1); 22 | $table->softDeletes(); 23 | $table->rememberToken(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('employees'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/assets/sass/_variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // Body 3 | $body-bg: #f5f8fa; 4 | 5 | // Borders 6 | $laravel-border-color: darken($body-bg, 10%); 7 | $list-group-border: $laravel-border-color; 8 | $navbar-default-border: $laravel-border-color; 9 | $panel-default-border: $laravel-border-color; 10 | $panel-inner-border: $laravel-border-color; 11 | 12 | // Brands 13 | $brand-primary: #3097D1; 14 | $brand-info: #8eb4cb; 15 | $brand-success: #2ab27b; 16 | $brand-warning: #cbb956; 17 | $brand-danger: #bf5329; 18 | 19 | // Typography 20 | $icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/"; 21 | $font-family-sans-serif: "Raleway", sans-serif; 22 | $font-size-base: 14px; 23 | $line-height-base: 1.6; 24 | $text-color: #636b6f; 25 | 26 | // Navbar 27 | $navbar-default-bg: #fff; 28 | 29 | // Buttons 30 | $btn-default-color: $text-color; 31 | 32 | // Inputs 33 | $input-border: lighten($text-color, 40%); 34 | $input-border-focus: lighten($brand-primary, 25%); 35 | $input-color-placeholder: lighten($text-color, 30%); 36 | 37 | // Panels 38 | $panel-default-heading-bg: #fff; 39 | -------------------------------------------------------------------------------- /tests/Unit/Employees/EmployeeUnitTest.php: -------------------------------------------------------------------------------- 1 | create(); 17 | 18 | $roleRepo = new RoleRepository(new Role); 19 | $userRole = $roleRepo->createRole(['name' => 'user']); 20 | 21 | $employeeRepo = new EmployeeRepository($employee); 22 | $employeeRepo->syncRoles([$userRole->id]); 23 | 24 | $employeeRoles = $employeeRepo->listRoles(); 25 | 26 | $this->assertCount(1, $employeeRoles->all()); 27 | 28 | $employeeRoles->each(function (Role $role) use ($userRole) { 29 | $this->assertEquals($userRole->name, $role->name); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_06_11_033553_create_category_product_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('category_id')->unsigned()->index(); 19 | $table->foreign('category_id')->references('id')->on('categories'); 20 | $table->integer('product_id')->unsigned()->index(); 21 | $table->foreign('product_id')->references('id')->on('products'); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('category_product'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Feature/Front/Categories/FrontCategoryFeatureTest.php: -------------------------------------------------------------------------------- 1 | create(); 16 | $product = factory(Product::class)->create(); 17 | 18 | $productRepo = new ProductRepository($product); 19 | $productRepo->syncCategories([$category->id]); 20 | 21 | $this 22 | ->get(route('front.category.slug', str_slug($category->name))) 23 | ->assertStatus(200) 24 | ->assertSee($category->name) 25 | ->assertSee($product->name) 26 | ->assertSee($product->description) 27 | ->assertSee("$product->quantity") 28 | ->assertSee("$product->price"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Controllers/Front/CategoryController.php: -------------------------------------------------------------------------------- 1 | categoryRepo = $categoryRepository; 16 | } 17 | 18 | /** 19 | * Find the category via the slug 20 | * 21 | * @param string $slug 22 | * @return \App\Shop\Categories\Category 23 | */ 24 | public function getCategory(string $slug) 25 | { 26 | $category = $this->categoryRepo->findCategoryBySlug(['slug' => $slug]); 27 | 28 | $repo = new CategoryRepository($category); 29 | 30 | return view('front.categories.category', [ 31 | 'category' => $category, 32 | 'products' => $repo->findProducts() 33 | ]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2017_06_13_091740_create_order_products_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('order_id')->unsigned()->index(); 19 | $table->foreign('order_id')->references('id')->on('orders'); 20 | $table->integer('product_id')->unsigned()->index(); 21 | $table->foreign('product_id')->references('id')->on('products'); 22 | $table->integer('quantity'); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('order_product'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2017_06_11_015526_create_categories_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name')->unique(); 19 | $table->string('slug'); 20 | $table->text('description')->nullable(); 21 | $table->string('cover')->nullable(); 22 | $table->integer('status')->default(0); 23 | $table->integer('parent_id')->default(1); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('categories'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2018_03_11_090249_create_attribute_value_product_attribute_table.php: -------------------------------------------------------------------------------- 1 | unsignedInteger('attribute_value_id'); 18 | $table->foreign('attribute_value_id')->references('id')->on('attribute_values'); 19 | $table->unsignedInteger('product_attribute_id'); 20 | $table->foreign('product_attribute_id')->references('id')->on('product_attributes'); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('attribute_value_product_attribute'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Shop/Roles/Repositories/RoleRepository.php: -------------------------------------------------------------------------------- 1 | model = $role; 25 | } 26 | 27 | /** 28 | * @param array $data 29 | * @return Role 30 | * @throws CreateRoleErrorException 31 | */ 32 | public function createRole(array $data) : Role 33 | { 34 | try { 35 | $role = new Role($data); 36 | $role->save(); 37 | return $role; 38 | } catch (QueryException $e) { 39 | throw new CreateRoleErrorException($e); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /database/factories/AddressModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Address::class, function (Faker\Generator $faker) { 19 | 20 | $customer = factory(Customer::class)->create(); 21 | 22 | return [ 23 | 'alias' => $faker->word, 24 | 'address_1' => $faker->streetName, 25 | 'address_2' => $faker->streetAddress, 26 | 'zip' => $faker->postcode, 27 | 'city_id' => 1, 28 | 'province_id' => 1, 29 | 'country_id' => 1, 30 | 'customer_id' => $customer->id, 31 | 'status' => 1 32 | ]; 33 | }); 34 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ResetPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /resources/views/front/products/product.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.front.app') 2 | 3 | @section('og') 4 | 5 | 6 | 7 | @if(!is_null($product->cover)) 8 | cover") }}"/> 9 | @endif 10 | @endsection 11 | 12 | @section('content') 13 |
14 |
15 |
16 | 23 |
24 |
25 | @include('layouts.front.product') 26 |
27 | @endsection -------------------------------------------------------------------------------- /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' => realpath(storage_path('framework/views')), 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Jeff Simons Decena 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/migrations/2017_06_10_225235_create_products_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('sku'); 19 | $table->string('name'); 20 | $table->string('slug'); 21 | $table->text('description')->nullable(); 22 | $table->string('cover')->nullable(); 23 | $table->integer('quantity'); 24 | $table->decimal('price'); 25 | $table->integer('status')->default(0); 26 | $table->timestamps(); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('products'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Shop/Categories/Repositories/Interfaces/CategoryRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | ], 21 | 22 | 'ses' => [ 23 | 'key' => env('SES_KEY'), 24 | 'secret' => env('SES_SECRET'), 25 | 'region' => 'us-east-1', 26 | ], 27 | 28 | 'sparkpost' => [ 29 | 'secret' => env('SPARKPOST_SECRET'), 30 | ], 31 | 32 | 'stripe' => [ 33 | 'model' => App\Shop\Customers\Customer::class, 34 | 'key' => env('STRIPE_KEY'), 35 | 'secret' => env('STRIPE_SECRET'), 36 | ], 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /resources/views/layouts/front/footer.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Http/Controllers/Front/HomeController.php: -------------------------------------------------------------------------------- 1 | categoryRepo = $categoryRepository; 25 | } 26 | 27 | /** 28 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 29 | */ 30 | public function index() 31 | { 32 | $newArrivals = $this->categoryRepo->findCategoryBySlug(['slug' => 'new-arrivals']); 33 | $featured = $this->categoryRepo->findCategoryBySlug(['slug' => 'featured']); 34 | 35 | return view('front.index', compact('newArrivals', 'featured')); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/factories/ProductModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Product::class, function (Faker\Generator $faker) { 19 | $product = $faker->unique()->sentence; 20 | $file = UploadedFile::fake()->image('product.png', 600, 600); 21 | 22 | return [ 23 | 'sku' => $this->faker->numberBetween(1111111, 999999), 24 | 'name' => $product, 25 | 'slug' => str_slug($product), 26 | 'description' => $this->faker->paragraph, 27 | 'cover' => $file->store('products', ['disk' => 'public']), 28 | 'quantity' => 10, 29 | 'price' => 5.00, 30 | 'status' => 1 31 | ]; 32 | }); 33 | -------------------------------------------------------------------------------- /resources/views/admin/shared/provinces.blade.php: -------------------------------------------------------------------------------- 1 | @if(!$provinces->isEmpty()) 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | @foreach($provinces as $province) 12 | 13 | 14 | 15 | 21 | 22 | @endforeach 23 | 24 |
NameStatusActions
{{ $province['name'] }}@include('layouts.status', ['status' => $province['status']]) 16 |
17 | Show 18 | Edit 19 |
20 |
25 | 28 | @endif -------------------------------------------------------------------------------- /app/Shop/ProductAttributes/Repositories/ProductAttributeRepository.php: -------------------------------------------------------------------------------- 1 | model = $productAttribute; 20 | } 21 | 22 | /** 23 | * @param int $id 24 | * @return mixed 25 | * @throws ProductAttributeNotFoundException 26 | */ 27 | public function findProductAttributeById(int $id) 28 | { 29 | try { 30 | return $this->findOneOrFail($id); 31 | } catch (ModelNotFoundException $e) { 32 | throw new ProductAttributeNotFoundException($e); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/factories/OrderModelFactory.php: -------------------------------------------------------------------------------- 1 | define(Order::class, function (Faker\Generator $faker) { 18 | 19 | return [ 20 | 'reference' => $faker->uuid, 21 | 'courier_id' => 1, 22 | 'customer_id' => 1, 23 | 'address_id' => 1, 24 | 'order_status_id' => 1, 25 | 'payment' => 'paypal', 26 | 'discounts' => $faker->randomFloat(2, 10, 999), 27 | 'total_products' => $faker->randomFloat(2, 10, 5555), 28 | 'tax' => $faker->randomFloat(2, 10, 9999), 29 | 'total' => $faker->randomFloat(2, 10, 9999), 30 | 'total_paid' => $faker->randomFloat(2, 10, 9999), 31 | 'invoice' => null, 32 | ]; 33 | }); 34 | -------------------------------------------------------------------------------- /resources/views/admin/dashboard.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.admin.app') 2 | 3 | @section('content') 4 | 5 |
6 | 7 | 8 |
9 |
10 |

Title

11 | 12 |
13 | 15 | 17 |
18 |
19 |
20 | Start creating your amazing application! 21 |
22 | 23 | 26 | 27 |
28 | 29 | 30 |
31 | 32 | @endsection 33 | -------------------------------------------------------------------------------- /app/Shop/Addresses/Repositories/Interfaces/AddressRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | define(Category::class, function (Faker\Generator $faker) { 19 | $name = $faker->unique()->randomElement([ 20 | 'Gear', 21 | 'Clothing', 22 | 'Shoes', 23 | 'Diapering', 24 | 'Feeding', 25 | 'Bath', 26 | 'Toys', 27 | 'Nursery', 28 | 'Household', 29 | 'Grocery' 30 | ]); 31 | 32 | $file = UploadedFile::fake()->image('category.png', 600, 600); 33 | 34 | return [ 35 | 'name' => $name, 36 | 'slug' => str_slug($name), 37 | 'description' => $faker->paragraph, 38 | 'cover' => $file->store('categories', ['disk' => 'public']), 39 | 'status' => 1 40 | ]; 41 | }); 42 | -------------------------------------------------------------------------------- /app/Mail/SendOrderToCustomerMailable.php: -------------------------------------------------------------------------------- 1 | order = $order; 25 | } 26 | 27 | /** 28 | * Build the message. 29 | * 30 | * @return $this 31 | */ 32 | public function build() 33 | { 34 | $data = [ 35 | 'order' => $this->order, 36 | 'products' => $this->order->products, 37 | 'customer' => $this->order->customer, 38 | 'courier' => $this->order->courier, 39 | 'address' => $this->order->address, 40 | 'status' => $this->order->orderStatus, 41 | 'payment' => $this->order->paymentMethod 42 | ]; 43 | 44 | return $this->view('emails.customer.sendOrderDetailsToCustomer', $data); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/Feature/Admin/Dashboard/DashboardFeatureTest.php: -------------------------------------------------------------------------------- 1 | actingAs($this->employee, 'admin') 15 | ->get(route('admin.dashboard')) 16 | ->assertStatus(200) 17 | ->assertSee('Dashboard') 18 | ->assertSee('List products') 19 | ->assertSee('Create product') 20 | ->assertSee('List categories') 21 | ->assertSee('Create category'); 22 | } 23 | 24 | /** @test */ 25 | public function it_should_not_show_admin_abilities_when_the_employee_is_not_admin() 26 | { 27 | $employee = factory(Employee::class)->create(); 28 | 29 | $this 30 | ->actingAs($employee, 'admin') 31 | ->get(route('admin.dashboard')) 32 | ->assertStatus(200) 33 | ->assertSee('Dashboard') 34 | ->assertDontSee('List products') 35 | ->assertDontSee('Create product') 36 | ->assertDontSee('List categories') 37 | ->assertDontSee('Create category'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Mail/sendEmailNotificationToAdminMailable.php: -------------------------------------------------------------------------------- 1 | order = $order; 25 | } 26 | 27 | /** 28 | * Build the message. 29 | * 30 | * @return $this 31 | */ 32 | public function build() 33 | { 34 | $data = [ 35 | 'order' => $this->order, 36 | 'products' => $this->order->products, 37 | 'customer' => $this->order->customer, 38 | 'courier' => $this->order->courier, 39 | 'address' => $this->order->address, 40 | 'status' => $this->order->orderStatus, 41 | 'payment' => $this->order->paymentMethod 42 | ]; 43 | 44 | return $this->view('emails.admin.OrderNotificationEmail', $data); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /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": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 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 --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "axios": "^0.17.1", 14 | "bootstrap-sass": "^3.3.7", 15 | "cross-env": "^5.1.3", 16 | "jquery": "^3.3.1", 17 | "laravel-mix": "^2.1.2", 18 | "lodash": "^4.17.5", 19 | "vue": "^2.5.13" 20 | }, 21 | "dependencies": { 22 | "admin-lte": "^2.3.8", 23 | "bootstrap": "^3.3.7", 24 | "datatables": "^1.10.13", 25 | "font-awesome": "^4.7.0", 26 | "ionicons": "^3.0.0", 27 | "select2": "^4.0.6-rc.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY=base64:85SiSOVH7/2NVYP5/DBrtBKbL51Nw0+6lF7tx2+jo8o= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | NODE_ENV=development 7 | 8 | LOG_CHANNEL=stack 9 | 10 | DB_CONNECTION=mysql 11 | DB_HOST=192.168.10.10 12 | DB_PORT=3306 13 | DB_DATABASE=homestead 14 | DB_USERNAME=homestead 15 | DB_PASSWORD=secret 16 | 17 | BROADCAST_DRIVER=log 18 | CACHE_DRIVER=file 19 | SESSION_DRIVER=file 20 | QUEUE_DRIVER=sync 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=null 30 | MAIL_PASSWORD=null 31 | MAIL_ENCRYPTION=null 32 | 33 | PUSHER_APP_ID= 34 | PUSHER_APP_KEY= 35 | PUSHER_APP_SECRET= 36 | 37 | SHIPPING_COST=0 38 | TAX_RATE=0 39 | DEFAULT_CURRENCY=usd 40 | CURRENCY_SYMBOL=$ 41 | 42 | MAILCHIMP_API_KEY= 43 | MAILCHIMP_LIST_ID= 44 | 45 | GOOGLE_ANALYTICS= 46 | 47 | PAYMENT_METHODS=paypal,stripe 48 | 49 | PP_ACCOUNT_ID=your.email-facilitator@yahoo.com 50 | PP_CLIENT_ID=xxxxxxxx 51 | PP_CLIENT_ID=xxxxxxxx 52 | PP_API_URL=https://api.sandbox.paypal.com 53 | PP_REDIRECT_URL=http://localhost/execute 54 | PP_CANCEL_URL=http://localhost/success 55 | PP_FAILED_URL=http://localhost/failed 56 | PP_MODE=sandbox 57 | 58 | STRIPE_KEY= 59 | STRIPE_SECRET= 60 | STRIPE_REDIRECT_URL= 61 | STRIPE_CANCEL_URL= 62 | STRIPE_FAILED_URL= -------------------------------------------------------------------------------- /resources/views/admin/employees/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.admin.app') 2 | 3 | @section('content') 4 | 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
IDNameEmail
{{ $employee->id }}{{ $employee->name }}{{ $employee->email }}
26 |
27 | 28 | 33 |
34 | 35 | 36 |
37 | 38 | @endsection 39 | -------------------------------------------------------------------------------- /database/seeds/CategoryProductsTableSeeder.php: -------------------------------------------------------------------------------- 1 | create()->each(function (Category $category) { 12 | factory(Product::class, 5)->make()->each(function(Product $product) use ($category) { 13 | $category->products()->save($product); 14 | }); 15 | }); 16 | 17 | factory(Category::class)->create([ 18 | 'name' => 'New Arrivals', 19 | 'slug' => 'new-arrivals', 20 | 'status' => 1 21 | ])->each(function (Category $category) { 22 | factory(Product::class, 3)->make()->each(function(Product $product) use ($category) { 23 | $category->products()->save($product); 24 | }); 25 | }); 26 | 27 | factory(Category::class)->create([ 28 | 'name' => 'Featured', 29 | 'slug' => 'featured', 30 | 'status' => 1 31 | ])->each(function (Category $category) { 32 | factory(Product::class, 3)->make()->each(function(Product $product) use ($category) { 33 | $category->products()->save($product); 34 | }); 35 | }); 36 | } 37 | } -------------------------------------------------------------------------------- /resources/views/layouts/errors-and-messages.blade.php: -------------------------------------------------------------------------------- 1 | @if($errors->all()) 2 | @foreach($errors->all() as $message) 3 |
4 |
5 |

6 | {{ $message }} 7 | 8 |

9 |
10 |
11 | @endforeach 12 | 13 | @elseif(session()->has('message')) 14 |
15 |
16 |

17 | {{ session()->get('message') }} 18 | 19 |

20 |
21 |
22 | @elseif(session()->has('error')) 23 |
24 |
25 |

26 | {{ session()->get('error') }} 27 | 28 |

29 |
30 |
31 | @endif -------------------------------------------------------------------------------- /app/Shop/Carts/Repositories/Interfaces/CartRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | model = $city; 17 | } 18 | 19 | public function listCities() 20 | { 21 | return $this->model->get(); 22 | } 23 | 24 | /** 25 | * @param int $id 26 | * @return City 27 | * @throws CityNotFoundException 28 | */ 29 | public function findCityById(int $id) : City 30 | { 31 | try { 32 | return $this->findOneOrFail($id); 33 | } catch (ModelNotFoundException $e) { 34 | throw new CityNotFoundException($e->getMessage()); 35 | } 36 | } 37 | 38 | /** 39 | * @param array $params 40 | * @return City 41 | */ 42 | public function updateCity(array $params) : City 43 | { 44 | $this->model->update($params); 45 | $this->model->save(); 46 | 47 | return $this->findCityById($this->model->id); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/Unit/Checkout/CheckoutUnitTest.php: -------------------------------------------------------------------------------- 1 | create(); 17 | 18 | $data = [ 19 | 'reference' => $this->faker->uuid, 20 | 'courier_id' => $this->courier->id, 21 | 'customer_id' => $this->customer->id, 22 | 'address_id' => $this->address->id, 23 | 'order_status_id' => $orderStatus->id, 24 | 'payment' => 'paypal', 25 | 'discounts' => 1.25, 26 | 'total_products' => 120.50, 27 | 'total' => 119.25, 28 | 'total_paid' => 119.25, 29 | 'tax' => 0 30 | ]; 31 | 32 | $checkoutRepo = new CheckoutRepository; 33 | $checkoutRepo->buildCheckoutItems($data); 34 | 35 | $orderRepo = new OrderRepository(new Order); 36 | $orders = $orderRepo->listOrders(); 37 | 38 | $orders->each(function (Order $order) use ($data) { 39 | $this->assertEquals($data['reference'], $order->reference); 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/Shop/Customers/Customer.php: -------------------------------------------------------------------------------- 1 | hasMany(Address::class)->where('status', 1); 47 | } 48 | 49 | /** 50 | * @return \Illuminate\Database\Eloquent\Relations\HasMany 51 | */ 52 | public function orders() 53 | { 54 | return $this->hasMany(Order::class); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/Feature/Front/Home/HomeFeatureTest.php: -------------------------------------------------------------------------------- 1 | create([ 15 | 'name' => 'New Arrivals', 16 | 'slug' => 'new-arrivals', 17 | 'status' => 1 18 | ])->each(function (Category $category) { 19 | factory(Product::class, 3)->make()->each(function (Product $product) use ($category) { 20 | $category->products()->save($product); 21 | }); 22 | }); 23 | 24 | factory(Category::class)->create([ 25 | 'name' => 'Featured', 26 | 'slug' => 'featured', 27 | 'status' => 1 28 | ])->each(function (Category $category) { 29 | factory(Product::class, 3)->make()->each(function (Product $product) use ($category) { 30 | $category->products()->save($product); 31 | }); 32 | }); 33 | 34 | $this 35 | ->get(route('home')) 36 | ->assertSee('Login') 37 | ->assertSee('Register') 38 | ->assertSee('New Arrivals') 39 | ->assertSee('Featured Products') 40 | ->assertStatus(200); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/Shop/Orders/Transformers/OrderTransformable.php: -------------------------------------------------------------------------------- 1 | courier = $courierRepo->findCourierById($order->courier_id); 27 | 28 | $customerRepo = new CustomerRepository(new Customer()); 29 | $order->customer = $customerRepo->findCustomerById($order->customer_id); 30 | 31 | $addressRepo = new AddressRepository(new Address()); 32 | $order->address = $addressRepo->findAddressById($order->address_id); 33 | 34 | $orderStatusRepo = new OrderStatusRepository(new OrderStatus()); 35 | $order->status = $orderStatusRepo->findOrderStatusById($order->order_status_id); 36 | 37 | return $order; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/views/admin/provinces/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.admin.app') 2 | 3 | @section('content') 4 | 5 |
6 | @include('layouts.errors-and-messages') 7 |
8 |
9 |
10 | 11 | {{ csrf_field() }} 12 |
13 | 14 | 15 |
16 |
17 | 18 | 24 |
25 |
26 | 27 | 28 |
29 | 30 | @endsection 31 | -------------------------------------------------------------------------------- /tests/Unit/AttributeValues/AttributeValueUnitTest.php: -------------------------------------------------------------------------------- 1 | 'small']); 16 | $attributeValueRepo = new AttributeValueRepository($attributeValue); 17 | 18 | $attribute = factory(Attribute::class)->create(); 19 | $createdValue = $attributeValueRepo->associateToAttribute($attribute); 20 | 21 | $attributeValueRepo2 = new AttributeValueRepository($createdValue); 22 | $removedAttribute = $attributeValueRepo2->dissociateFromAttribute(); 23 | 24 | $this->assertTrue($removedAttribute); 25 | } 26 | 27 | /** @test */ 28 | public function it_can_be_associated_with_the_attribute() 29 | { 30 | $attributeValue = new AttributeValue(['value' => 'sizes']); 31 | $attributeValueRepo = new AttributeValueRepository($attributeValue); 32 | 33 | $attribute = factory(Attribute::class)->create(); 34 | $attributeValueRepo->associateToAttribute($attribute); 35 | 36 | $this->assertCount(1, $attribute->values->all()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests/Feature 14 | 15 | 16 | 17 | ./tests/Unit 18 | 19 | 20 | 21 | 22 | ./app 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /database/migrations/2017_06_11_073305_create_address_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('alias'); 19 | $table->string('address_1'); 20 | $table->string('address_2')->nullable(); 21 | $table->string('zip')->nullable(); 22 | $table->integer('city_id')->nullable(); 23 | $table->integer('province_id')->nullable(); 24 | $table->integer('country_id')->unsigned()->index(); 25 | $table->foreign('country_id')->references('id')->on('countries'); 26 | $table->integer('customer_id')->unsigned()->index(); 27 | $table->foreign('customer_id')->references('id')->on('customers'); 28 | $table->integer('status')->default(0); 29 | $table->softDeletes(); 30 | $table->timestamps(); 31 | }); 32 | } 33 | 34 | /** 35 | * Reverse the migrations. 36 | * 37 | * @return void 38 | */ 39 | public function down() 40 | { 41 | Schema::dropIfExists('addresses'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /resources/views/layouts/errors/403.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Unauthorized 9 | 10 | 11 | 12 | 13 | 14 | 46 | 47 | 48 |
49 |
50 |
51 |

{{$error}}

52 |
53 |
54 |
55 | 56 | 57 | -------------------------------------------------------------------------------- /resources/views/admin/cities/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.admin.app') 2 | 3 | @section('content') 4 | 5 |
6 | @include('layouts.errors-and-messages') 7 |
8 |
9 |
10 | 11 | {{ csrf_field() }} 12 |
13 | 14 | 15 |
16 |
17 | 18 | 24 |
25 |
26 | 27 | 28 |
29 | 30 | @endsection 31 | -------------------------------------------------------------------------------- /resources/views/admin/attributes/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.admin.app') 2 | 3 | @section('content') 4 | 5 |
6 | @include('layouts.errors-and-messages') 7 |
8 |
9 |
10 |
11 | {{ csrf_field() }} 12 |
13 |
14 | 15 | 16 |
17 |
18 |
19 |
20 | 21 | 27 |
28 |
29 | 30 |
31 | 32 | @endsection 33 | -------------------------------------------------------------------------------- /app/Shop/Checkout/CheckoutRepository.php: -------------------------------------------------------------------------------- 1 | create([ 25 | 'reference' => $data['reference'], 26 | 'courier_id' => $data['courier_id'], 27 | 'customer_id' => $data['customer_id'], 28 | 'address_id' => $data['address_id'], 29 | 'order_status_id' => $data['order_status_id'], 30 | 'payment' => $data['payment'], 31 | 'discounts' => $data['discounts'], 32 | 'total_products' => $data['total_products'], 33 | 'total' => $data['total'], 34 | 'total_paid' => $data['total_paid'], 35 | 'tax' => $data['tax'] 36 | ]); 37 | 38 | $orderProductRepo->buildOrderDetails($order, $cartRepo->getCartItems()); 39 | 40 | return $order; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Unit/Cities/CityUnitTest.php: -------------------------------------------------------------------------------- 1 | create(); 16 | $cityRepo = new CityRepository($city); 17 | 18 | $this->assertCount(1, $cityRepo->listCities()); 19 | } 20 | 21 | /** @test */ 22 | public function it_can_update_the_city() 23 | { 24 | $city = factory(City::class)->create(); 25 | $cityRepo = new CityRepository($city); 26 | 27 | $update = ['name' => 'Manila']; 28 | $cityRepo->updateCity($update); 29 | 30 | $this->assertEquals($update['name'], $city->name); 31 | } 32 | 33 | /** @test */ 34 | public function it_will_error_when_city_is_not_found() 35 | { 36 | $this->expectException(CityNotFoundException::class); 37 | 38 | $cityRepo = new CityRepository(new City); 39 | $cityRepo->findCityById(999); 40 | } 41 | 42 | /** @test */ 43 | public function it_can_find_the_city() 44 | { 45 | $city = factory(City::class)->create(); 46 | $cityRepo = new CityRepository(new City); 47 | $found = $cityRepo->findCityById($city->id); 48 | 49 | $this->assertEquals($city->name, $found->name); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /resources/views/layouts/errors/503.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Service Unavailable 9 | 10 | 11 | 12 | 13 | 14 | 46 | 47 | 48 |
49 |
50 |
51 |

Ooops, server error occurred.

Please check again later. 52 |
53 |
54 |
55 | 56 | 57 | --------------------------------------------------------------------------------