├── src ├── main │ ├── webapp │ │ ├── assets │ │ │ ├── richtexteditor │ │ │ │ ├── plugins │ │ │ │ │ ├── -combine-plugin.txt │ │ │ │ │ ├── tui.image-editor │ │ │ │ │ │ ├── note.txt │ │ │ │ │ │ └── tui-color-picker.min.css │ │ │ │ │ ├── insertgallery.js │ │ │ │ │ ├── samples │ │ │ │ │ │ └── insertcode_v1.js │ │ │ │ │ ├── inserttemplate.js │ │ │ │ │ └── html2pdf.js │ │ │ │ ├── runtime │ │ │ │ │ ├── richtexteditor_preview.js │ │ │ │ │ └── images │ │ │ │ │ │ ├── 1x1.gif │ │ │ │ │ │ ├── formbn.gif │ │ │ │ │ │ ├── cpns_hue2.png │ │ │ │ │ │ ├── cpie_Color.cur │ │ │ │ │ │ ├── cpie_WebSafe.gif │ │ │ │ │ │ ├── cpns_Color.cur │ │ │ │ │ │ ├── cpns_WebSafe.gif │ │ │ │ │ │ ├── multiclavier.gif │ │ │ │ │ │ ├── cpie_gradients.png │ │ │ │ │ │ ├── cpns_Vertical1.png │ │ │ │ │ │ ├── cpns_Vertical2.png │ │ │ │ │ │ ├── cpns_gradients.png │ │ │ │ │ │ ├── cpns_ColorSpace1.png │ │ │ │ │ │ ├── cpns_ColorSpace2.png │ │ │ │ │ │ ├── cpie_VerticalPosition.gif │ │ │ │ │ │ ├── cpns_VerticalPosition.gif │ │ │ │ │ │ ├── cpie_GradientPositionDark.gif │ │ │ │ │ │ ├── cpie_GradientPositionLight.gif │ │ │ │ │ │ ├── cpns_GradientPositionDark.gif │ │ │ │ │ │ └── cpns_GradientPositionLight.gif │ │ │ │ └── lang │ │ │ │ │ ├── rte-lang-en.js │ │ │ │ │ └── rte-lang.js │ │ │ ├── fonts │ │ │ │ ├── slick.eot │ │ │ │ ├── slick.ttf │ │ │ │ ├── slick.woff │ │ │ │ ├── fa-thin-100.ttf │ │ │ │ ├── fa-brands-400.ttf │ │ │ │ ├── fa-light-300.ttf │ │ │ │ ├── fa-solid-900.ttf │ │ │ │ ├── fa-thin-100.woff2 │ │ │ │ ├── fa-brands-400.woff2 │ │ │ │ ├── fa-duotone-900.ttf │ │ │ │ ├── fa-duotone-900.woff2 │ │ │ │ ├── fa-light-300.woff2 │ │ │ │ ├── fa-regular-400.ttf │ │ │ │ ├── fa-regular-400.woff2 │ │ │ │ ├── fa-solid-900.woff2 │ │ │ │ ├── fa-sharp-light-300.ttf │ │ │ │ ├── fa-sharp-solid-900.ttf │ │ │ │ ├── fa-sharp-thin-100.ttf │ │ │ │ ├── fa-v4compatibility.ttf │ │ │ │ ├── fa-sharp-light-300.woff2 │ │ │ │ ├── fa-sharp-regular-400.ttf │ │ │ │ ├── fa-sharp-solid-900.woff2 │ │ │ │ ├── fa-sharp-thin-100.woff2 │ │ │ │ ├── fa-v4compatibility.woff2 │ │ │ │ ├── fa-sharp-regular-400.woff2 │ │ │ │ └── slick.svg │ │ │ ├── images │ │ │ │ ├── avatar.png │ │ │ │ ├── favicon.png │ │ │ │ ├── icons │ │ │ │ │ ├── visa.png │ │ │ │ │ ├── service1.png │ │ │ │ │ ├── service2.png │ │ │ │ │ ├── service3.png │ │ │ │ │ ├── service4.png │ │ │ │ │ ├── service5.png │ │ │ │ │ └── mastercard.png │ │ │ │ ├── logo │ │ │ │ │ ├── logo.png │ │ │ │ │ ├── logo-large.png │ │ │ │ │ └── logo-light.png │ │ │ │ ├── ajax-loader.gif │ │ │ │ ├── bg │ │ │ │ │ └── bg-image-10.jpg │ │ │ │ ├── product │ │ │ │ │ ├── main-01.png │ │ │ │ │ ├── main-02.png │ │ │ │ │ ├── main-03.png │ │ │ │ │ ├── product-01.png │ │ │ │ │ ├── product-02.png │ │ │ │ │ ├── product-03.png │ │ │ │ │ └── categories │ │ │ │ │ │ └── sample.png │ │ │ │ └── others │ │ │ │ │ ├── app-store.png │ │ │ │ │ └── play-store.png │ │ │ ├── css │ │ │ │ └── vendor │ │ │ │ │ ├── flaticon │ │ │ │ │ ├── flaticon.eot │ │ │ │ │ ├── flaticon.ttf │ │ │ │ │ ├── flaticon.woff │ │ │ │ │ ├── flaticon.woff2 │ │ │ │ │ └── flaticon.css │ │ │ │ │ ├── slick.css │ │ │ │ │ └── slick-theme.css │ │ │ └── js │ │ │ │ ├── vendor │ │ │ │ ├── counterup.js │ │ │ │ ├── jquery.ui.touch-punch.min.js │ │ │ │ ├── sal.js │ │ │ │ ├── js.cookie.js │ │ │ │ ├── jquery.countdown.min.js │ │ │ │ └── imagesloaded.pkgd.min.js │ │ │ │ ├── verify-account.js │ │ │ │ ├── sign-in.js │ │ │ │ ├── sign-up.js │ │ │ │ └── index.js │ │ ├── uploads │ │ │ └── product │ │ │ │ ├── 4 │ │ │ │ ├── 1763915055843.png │ │ │ │ ├── 1763915055852.jpg │ │ │ │ └── 1763915055856.jpg │ │ │ │ └── 5 │ │ │ │ ├── 1763915242697.jpg │ │ │ │ ├── 1763915242699.png │ │ │ │ └── 1763915242703.jpg │ │ ├── WEB-INF │ │ │ └── web.xml │ │ ├── verify-account.html │ │ └── sign-in.html │ ├── resources │ │ ├── app.properties │ │ └── hibernate.cfg.xml │ └── java │ │ └── lk │ │ └── jiat │ │ └── smarttrade │ │ ├── config │ │ └── AppConfig.java │ │ ├── annotation │ │ └── IsUser.java │ │ ├── dto │ │ ├── CityDTO.java │ │ ├── DeliveryTypeDTO.java │ │ ├── StockDTO.java │ │ ├── CheckoutDTO.java │ │ ├── UserAddressDTO.java │ │ ├── CheckoutRequestDTO.java │ │ ├── CartDTO.java │ │ ├── UserDTO.java │ │ ├── ProductDTO.java │ │ └── PayHereDTO.java │ │ ├── util │ │ ├── AppUtil.java │ │ ├── HibernateUtil.java │ │ ├── Env.java │ │ └── PayHereUtil.java │ │ ├── entity │ │ ├── City.java │ │ ├── Color.java │ │ ├── Quality.java │ │ ├── Storage.java │ │ ├── Brand.java │ │ ├── Model.java │ │ ├── BaseEntity.java │ │ ├── Status.java │ │ ├── Cart.java │ │ ├── DeliveryType.java │ │ ├── OrderItem.java │ │ ├── Order.java │ │ ├── Discount.java │ │ ├── Stock.java │ │ ├── Seller.java │ │ ├── Address.java │ │ ├── User.java │ │ └── Product.java │ │ ├── listener │ │ └── ContextPathListener.java │ │ ├── controller │ │ ├── TestController.java │ │ └── api │ │ │ ├── VerificationController.java │ │ │ ├── CheckoutController.java │ │ │ ├── CartController.java │ │ │ ├── PaymentGatewayController.java │ │ │ ├── ProfileController.java │ │ │ ├── UserController.java │ │ │ ├── ContentController.java │ │ │ └── ProductController.java │ │ ├── service │ │ ├── CityService.java │ │ ├── OrderService.java │ │ └── FileUploadService.java │ │ ├── middleware │ │ ├── AccessControlFilter.java │ │ ├── AuthAccessFilter.java │ │ └── AuthFilter.java │ │ ├── validation │ │ └── Validator.java │ │ ├── Main.java │ │ ├── mail │ │ ├── Mailable.java │ │ └── VerificationMail.java │ │ └── provider │ │ └── MailServiceProvider.java └── test │ └── java │ └── Test.java ├── .idea ├── vcs.xml ├── .gitignore ├── encodings.xml ├── data_source_mapping.xml ├── jpa.xml ├── webContexts.xml ├── misc.xml ├── dataSources.xml └── inspectionProfiles │ └── Project_Default.xml ├── .gitignore └── pom.xml /src/main/webapp/assets/richtexteditor/plugins/-combine-plugin.txt: -------------------------------------------------------------------------------- 1 | 2 | //END of all_plugins.js -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/richtexteditor_preview.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | console.log("richtexteditor_preview.js load OK") 4 | 5 | -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/slick.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/slick.eot -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/slick.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/slick.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/slick.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/slick.woff -------------------------------------------------------------------------------- /src/main/webapp/assets/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/avatar.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/favicon.png -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-thin-100.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-thin-100.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/images/icons/visa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/icons/visa.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/logo/logo.png -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/lang/rte-lang-en.js: -------------------------------------------------------------------------------- 1 | //English texts are included in rte-config.js 2 | 3 | //Include this file or not , does not matter 4 | -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/plugins/tui.image-editor/note.txt: -------------------------------------------------------------------------------- 1 | tui.image-editor 2 | 3 | MIT License 4 | 5 | https://github.com/nhn/tui.image-editor/ 6 | -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-light-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-light-300.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-thin-100.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-thin-100.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/images/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/ajax-loader.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-duotone-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-duotone-900.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-duotone-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-duotone-900.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-light-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-light-300.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/images/bg/bg-image-10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/bg/bg-image-10.jpg -------------------------------------------------------------------------------- /src/main/webapp/assets/images/icons/service1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/icons/service1.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/icons/service2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/icons/service2.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/icons/service3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/icons/service3.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/icons/service4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/icons/service4.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/icons/service5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/icons/service5.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/logo/logo-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/logo/logo-large.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/logo/logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/logo/logo-light.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/product/main-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/product/main-01.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/product/main-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/product/main-02.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/product/main-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/product/main-03.png -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-sharp-light-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-sharp-light-300.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-sharp-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-sharp-solid-900.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-sharp-thin-100.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-sharp-thin-100.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-v4compatibility.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-v4compatibility.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/images/icons/mastercard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/icons/mastercard.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/others/app-store.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/others/app-store.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/others/play-store.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/others/play-store.png -------------------------------------------------------------------------------- /src/main/webapp/uploads/product/4/1763915055843.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/uploads/product/4/1763915055843.png -------------------------------------------------------------------------------- /src/main/webapp/uploads/product/4/1763915055852.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/uploads/product/4/1763915055852.jpg -------------------------------------------------------------------------------- /src/main/webapp/uploads/product/4/1763915055856.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/uploads/product/4/1763915055856.jpg -------------------------------------------------------------------------------- /src/main/webapp/uploads/product/5/1763915242697.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/uploads/product/5/1763915242697.jpg -------------------------------------------------------------------------------- /src/main/webapp/uploads/product/5/1763915242699.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/uploads/product/5/1763915242699.png -------------------------------------------------------------------------------- /src/main/webapp/uploads/product/5/1763915242703.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/uploads/product/5/1763915242703.jpg -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-sharp-light-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-sharp-light-300.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-sharp-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-sharp-regular-400.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-sharp-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-sharp-solid-900.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-sharp-thin-100.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-sharp-thin-100.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-v4compatibility.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-v4compatibility.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/images/product/product-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/product/product-01.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/product/product-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/product/product-02.png -------------------------------------------------------------------------------- /src/main/webapp/assets/images/product/product-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/product/product-03.png -------------------------------------------------------------------------------- /src/main/webapp/assets/css/vendor/flaticon/flaticon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/css/vendor/flaticon/flaticon.eot -------------------------------------------------------------------------------- /src/main/webapp/assets/css/vendor/flaticon/flaticon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/css/vendor/flaticon/flaticon.ttf -------------------------------------------------------------------------------- /src/main/webapp/assets/css/vendor/flaticon/flaticon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/css/vendor/flaticon/flaticon.woff -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/fa-sharp-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/fonts/fa-sharp-regular-400.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/css/vendor/flaticon/flaticon.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/css/vendor/flaticon/flaticon.woff2 -------------------------------------------------------------------------------- /src/main/webapp/assets/images/product/categories/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/images/product/categories/sample.png -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/1x1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/1x1.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/formbn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/formbn.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_hue2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_hue2.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpie_Color.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpie_Color.cur -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpie_WebSafe.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpie_WebSafe.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_Color.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_Color.cur -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_WebSafe.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_WebSafe.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/multiclavier.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/multiclavier.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpie_gradients.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpie_gradients.png -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_Vertical1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_Vertical1.png -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_Vertical2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_Vertical2.png -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_gradients.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_gradients.png -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_ColorSpace1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_ColorSpace1.png -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_ColorSpace2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_ColorSpace2.png -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpie_VerticalPosition.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpie_VerticalPosition.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_VerticalPosition.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_VerticalPosition.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpie_GradientPositionDark.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpie_GradientPositionDark.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpie_GradientPositionLight.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpie_GradientPositionLight.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_GradientPositionDark.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_GradientPositionDark.gif -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/runtime/images/cpns_GradientPositionLight.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilharaAnjana/SmartTrade-Athena_Giraffe/HEAD/src/main/webapp/assets/richtexteditor/runtime/images/cpns_GradientPositionLight.gif -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/app.properties: -------------------------------------------------------------------------------- 1 | mail.host=sandbox.smtp.mailtrap.io 2 | mail.port=2525 3 | mail.username=e7c9c34cfb5b44 4 | mail.password=d09dbcb0356ae8 5 | app.mail=info.smarttrade@gmail.com 6 | app.name=SmartTrade 7 | app.url=http://localhost:8080/smarttrade 8 | app.public.url=https://6089daf4b63b.ngrok-free.app -------------------------------------------------------------------------------- /.idea/data_source_mapping.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/jpa.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/webContexts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.config; 2 | 3 | import org.glassfish.jersey.server.ResourceConfig; 4 | 5 | public class AppConfig extends ResourceConfig { 6 | public AppConfig(){ 7 | packages("lk.jiat.smarttrade.controller"); 8 | packages("lk.jiat.smarttrade.middleware"); 9 | register(org.glassfish.jersey.media.multipart.MultiPartFeature.class); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/annotation/IsUser.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.annotation; 2 | 3 | import jakarta.ws.rs.NameBinding; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | @NameBinding 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target({ElementType.TYPE, ElementType.METHOD}) 13 | public @interface IsUser { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/CityDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | public class CityDTO implements Serializable { 6 | private int id; 7 | private String name; 8 | 9 | public int getId() { 10 | return id; 11 | } 12 | 13 | public void setId(int id) { 14 | this.id = id; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | .kotlin 6 | 7 | ### IntelliJ IDEA ### 8 | .idea 9 | .idea/modules.xml 10 | .idea/jarRepositories.xml 11 | .idea/compiler.xml 12 | .idea/libraries/ 13 | *.iws 14 | *.iml 15 | *.ipr 16 | 17 | ### Eclipse ### 18 | .apt_generated 19 | .classpath 20 | .factorypath 21 | .project 22 | .settings 23 | .springBeans 24 | .sts4-cache 25 | 26 | ### NetBeans ### 27 | /nbproject/private/ 28 | /nbbuild/ 29 | /dist/ 30 | /nbdist/ 31 | /.nb-gradle/ 32 | build/ 33 | !**/src/main/**/build/ 34 | !**/src/test/**/build/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | 39 | ### Mac OS ### 40 | .DS_Store 41 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/util/AppUtil.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.util; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.security.SecureRandom; 6 | 7 | public class AppUtil { 8 | public static final Gson GSON = new Gson(); 9 | public static final int DEFAULT_SELECTOR_VALUE = 0; 10 | public static final String MAIN_APP_CURRENCY = "LKR"; 11 | public static final String APP_COUNTRY = "Sri Lanka"; 12 | private static final SecureRandom SECURE_RANDOM = new SecureRandom(); 13 | 14 | public static String generateCode() { 15 | int randomNumber = SECURE_RANDOM.nextInt(1_000_000); 16 | return String.format("%6d", randomNumber); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/City.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | public class City implements Serializable { 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.IDENTITY) 11 | private int id; 12 | @Column(length = 50, nullable = false) 13 | private String name; 14 | 15 | public int getId() { 16 | return id; 17 | } 18 | 19 | public void setId(int id) { 20 | this.id = id; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/listener/ContextPathListener.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.listener; 2 | 3 | import jakarta.servlet.ServletContextEvent; 4 | import jakarta.servlet.ServletContextListener; 5 | import jakarta.servlet.annotation.WebListener; 6 | import lk.jiat.smarttrade.provider.MailServiceProvider; 7 | 8 | @WebListener 9 | public class ContextPathListener implements ServletContextListener { 10 | @Override 11 | public void contextInitialized(ServletContextEvent sce) { 12 | MailServiceProvider.getInstance().start(); 13 | } 14 | 15 | @Override 16 | public void contextDestroyed(ServletContextEvent sce) { 17 | MailServiceProvider.getInstance().shutdown(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Color.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | public class Color implements Serializable { 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.IDENTITY) 11 | private int id; 12 | 13 | @Column(length = 45, nullable = false) 14 | private String value; 15 | 16 | public int getId() { 17 | return id; 18 | } 19 | 20 | public void setId(int id) { 21 | this.id = id; 22 | } 23 | 24 | public String getValue() { 25 | return value; 26 | } 27 | 28 | public void setValue(String value) { 29 | this.value = value; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Quality.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | public class Quality implements Serializable { 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.IDENTITY) 11 | private int id; 12 | 13 | @Column(length = 45, nullable = false) 14 | private String value; 15 | 16 | public int getId() { 17 | return id; 18 | } 19 | 20 | public void setId(int id) { 21 | this.id = id; 22 | } 23 | 24 | public String getValue() { 25 | return value; 26 | } 27 | 28 | public void setValue(String value) { 29 | this.value = value; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Storage.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | public class Storage implements Serializable { 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.IDENTITY) 11 | private int id; 12 | 13 | @Column(length = 45, nullable = false) 14 | private String value; 15 | 16 | public int getId() { 17 | return id; 18 | } 19 | 20 | public void setId(int id) { 21 | this.id = id; 22 | } 23 | 24 | public String getValue() { 25 | return value; 26 | } 27 | 28 | public void setValue(String value) { 29 | this.value = value; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/DeliveryTypeDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | public class DeliveryTypeDTO implements Serializable { 6 | private int id; 7 | private String name; 8 | private double price; 9 | 10 | public int getId() { 11 | return id; 12 | } 13 | 14 | public void setId(int id) { 15 | this.id = id; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public void setName(String name) { 23 | this.name = name; 24 | } 25 | 26 | public double getPrice() { 27 | return price; 28 | } 29 | 30 | public void setPrice(double price) { 31 | this.price = price; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/util/HibernateUtil.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.util; 2 | 3 | import org.hibernate.HibernateException; 4 | import org.hibernate.SessionFactory; 5 | import org.hibernate.cfg.Configuration; 6 | 7 | public class HibernateUtil { 8 | private static final SessionFactory sessionFactory; 9 | static { 10 | try{ 11 | 12 | sessionFactory = new Configuration().configure().buildSessionFactory(); 13 | }catch (HibernateException e){ 14 | throw new ExceptionInInitializerError("SessionFactory creation failed: "+e.getMessage()); 15 | } 16 | } 17 | public static SessionFactory getSessionFactory(){ 18 | return sessionFactory; 19 | } 20 | public static void shutdown(){ 21 | sessionFactory.close(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/util/Env.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.Properties; 6 | 7 | public class Env { 8 | private static final Properties APP_PROPERTIES = new Properties(); 9 | 10 | static { 11 | try { 12 | InputStream inputStream = Env.class.getClassLoader().getResourceAsStream("app.properties"); 13 | APP_PROPERTIES.load(inputStream); 14 | } catch (IOException e) { 15 | throw new RuntimeException("Application properties loading failed: " + e.getMessage()); 16 | } 17 | } 18 | 19 | public static String get(String key){ 20 | return APP_PROPERTIES.getProperty(key); 21 | } 22 | public static Properties getAppProperties(){ 23 | return APP_PROPERTIES; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller; 2 | 3 | import jakarta.ws.rs.GET; 4 | import jakarta.ws.rs.Path; 5 | import jakarta.ws.rs.Produces; 6 | import jakarta.ws.rs.core.MediaType; 7 | import jakarta.ws.rs.core.Response; 8 | import lk.jiat.smarttrade.annotation.IsUser; 9 | 10 | import java.io.IOException; 11 | import java.nio.file.Files; 12 | import java.nio.file.Paths; 13 | 14 | @Path("/test") 15 | public class TestController { 16 | @IsUser 17 | @GET 18 | @Produces(MediaType.TEXT_HTML) 19 | public Response test() { 20 | try { 21 | return Response.ok().entity(new String(Files.readAllBytes(Paths.get("src/main/webapp/sign-in.html")))).build(); 22 | } catch (IOException e) { 23 | return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); 24 | 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.idea/dataSources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | mysql.8 6 | true 7 | com.mysql.cj.jdbc.Driver 8 | jdbc:mysql://localhost:3306/smarttrade 9 | 10 | 11 | 12 | 13 | 14 | $ProjectFileDir$ 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/api/VerificationController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller.api; 2 | 3 | import com.google.gson.Gson; 4 | import jakarta.ws.rs.*; 5 | import jakarta.ws.rs.core.MediaType; 6 | import jakarta.ws.rs.core.Response; 7 | import lk.jiat.smarttrade.annotation.IsUser; 8 | import lk.jiat.smarttrade.dto.UserDTO; 9 | import lk.jiat.smarttrade.service.UserService; 10 | 11 | @IsUser 12 | @Path("/verify-accounts") 13 | public class VerificationController { 14 | @POST 15 | @Consumes(MediaType.APPLICATION_JSON) 16 | @Produces(MediaType.APPLICATION_JSON) 17 | public Response verifyUserAccount(String jsonData) { 18 | Gson gson = new Gson(); 19 | UserDTO userDTO = gson.fromJson(jsonData, UserDTO.class); 20 | String responseJson = new UserService().verifyUserAccount(userDTO); 21 | return Response.ok().entity(responseJson).build(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/service/CityService.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.service; 2 | 3 | import com.google.gson.JsonObject; 4 | import lk.jiat.smarttrade.entity.City; 5 | import lk.jiat.smarttrade.util.AppUtil; 6 | import lk.jiat.smarttrade.util.HibernateUtil; 7 | import org.hibernate.Session; 8 | 9 | import java.util.List; 10 | 11 | public class CityService { 12 | 13 | public String loadAllCities() { 14 | JsonObject responseObject = new JsonObject(); 15 | 16 | /// city-loading-part-start 17 | Session hibernateSession = HibernateUtil.getSessionFactory().openSession(); 18 | List cityList = hibernateSession.createQuery("FROM City c", City.class).getResultList(); 19 | responseObject.add("cities", AppUtil.GSON.toJsonTree(cityList)); 20 | hibernateSession.close(); 21 | /// city-loading-part-end 22 | 23 | return AppUtil.GSON.toJson(responseObject); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Brand.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | @Entity 10 | public class Brand implements Serializable { 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private int id; 14 | 15 | @Column(length = 100, nullable = false) 16 | private String name; 17 | 18 | @OneToMany(mappedBy = "brand") 19 | private Set models = new HashSet<>(); 20 | 21 | public Set getModels() { 22 | return models; 23 | } 24 | 25 | public int getId() { 26 | return id; 27 | } 28 | 29 | public void setId(int id) { 30 | this.id = id; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public void setName(String name) { 38 | this.name = name; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Model.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | public class Model implements Serializable { 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.IDENTITY) 11 | private int id; 12 | @Column(length = 100, nullable = false) 13 | private String name; 14 | 15 | @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 16 | @JoinColumn(name = "brand_id") 17 | private Brand brand; 18 | 19 | public Brand getBrand() { 20 | return brand; 21 | } 22 | 23 | public void setBrand(Brand brand) { 24 | this.brand = brand; 25 | } 26 | 27 | public int getId() { 28 | return id; 29 | } 30 | 31 | public void setId(int id) { 32 | this.id = id; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public void setName(String name) { 40 | this.name = name; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/middleware/AccessControlFilter.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.middleware; 2 | 3 | 4 | import jakarta.servlet.*; 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import jakarta.servlet.http.HttpServletResponse; 7 | import jakarta.servlet.http.HttpSession; 8 | 9 | import java.io.IOException; 10 | 11 | public class AccessControlFilter implements Filter { 12 | @Override 13 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 14 | HttpServletRequest request = (HttpServletRequest) servletRequest; 15 | HttpServletResponse response = (HttpServletResponse) servletResponse; 16 | 17 | HttpSession httpSession = request.getSession(false); 18 | if (httpSession != null && httpSession.getAttribute("user") != null) { 19 | filterChain.doFilter(servletRequest, servletResponse); 20 | } else { 21 | response.sendRedirect("sign-in.html"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.MappedSuperclass; 5 | import org.hibernate.annotations.CreationTimestamp; 6 | import org.hibernate.annotations.UpdateTimestamp; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | @MappedSuperclass 12 | public class BaseEntity implements Serializable { 13 | @CreationTimestamp 14 | @Column(name = "created_at", updatable = false, nullable = false) 15 | private LocalDateTime createdAt; 16 | 17 | @UpdateTimestamp 18 | @Column(name = "updated_at", nullable = false) 19 | private LocalDateTime updatedAt; 20 | 21 | public LocalDateTime getCreatedAt() { 22 | return createdAt; 23 | } 24 | 25 | public void setCreatedAt(LocalDateTime createdAt) { 26 | this.createdAt = createdAt; 27 | } 28 | 29 | public LocalDateTime getUpdatedAt() { 30 | return updatedAt; 31 | } 32 | 33 | public void setUpdatedAt(LocalDateTime updatedAt) { 34 | this.updatedAt = updatedAt; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/StockDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | public class StockDTO { 4 | private int stockId; 5 | private int productId; 6 | private int qty; 7 | private double price; 8 | private String createdAt; 9 | 10 | public int getStockId() { 11 | return stockId; 12 | } 13 | 14 | public void setStockId(int stockId) { 15 | this.stockId = stockId; 16 | } 17 | 18 | public int getProductId() { 19 | return productId; 20 | } 21 | 22 | public void setProductId(int productId) { 23 | this.productId = productId; 24 | } 25 | 26 | public int getQty() { 27 | return qty; 28 | } 29 | 30 | public void setQty(int qty) { 31 | this.qty = qty; 32 | } 33 | 34 | public double getPrice() { 35 | return price; 36 | } 37 | 38 | public void setPrice(double price) { 39 | this.price = price; 40 | } 41 | 42 | public String getCreatedAt() { 43 | return createdAt; 44 | } 45 | 46 | public void setCreatedAt(String createdAt) { 47 | this.createdAt = createdAt; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Status.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | @NamedQuery(name = "Status.findByValue", 9 | query = "FROM Status s WHERE s.value=:value") 10 | public class Status implements Serializable { 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private int id; 14 | 15 | @Column(length = 45, nullable = false, unique = true) 16 | private String value; 17 | 18 | public int getId() { 19 | return id; 20 | } 21 | 22 | public void setId(int id) { 23 | this.id = id; 24 | } 25 | 26 | public String getValue() { 27 | return value; 28 | } 29 | 30 | public void setValue(String value) { 31 | this.value = value; 32 | } 33 | 34 | public enum Type { 35 | ACTIVE, 36 | PENDING, 37 | INACTIVE, 38 | BLOCKED, 39 | DELIVERED, 40 | PACKING, 41 | APPROVED, 42 | REJECTED, 43 | CANCELED, 44 | VERIFIED, 45 | RECEIVED, 46 | COMPLETED 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/middleware/AuthAccessFilter.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.middleware; 2 | 3 | import jakarta.servlet.*; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import jakarta.servlet.http.HttpSession; 7 | 8 | import java.io.IOException; 9 | 10 | public class AuthAccessFilter implements Filter { 11 | @Override 12 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 13 | HttpServletRequest request = (HttpServletRequest) servletRequest; 14 | HttpServletResponse response = (HttpServletResponse) servletResponse; 15 | 16 | HttpSession httpSession = request.getSession(false); 17 | if (httpSession != null && httpSession.getAttribute("user") != null) { 18 | response.sendRedirect("index.html"); 19 | } else { 20 | filterChain.doFilter(servletRequest, servletResponse); 21 | response.setHeader("Cache-Control", "no-cache, no-store, revalidate"); 22 | response.setHeader("Pragma", "no-cache"); 23 | response.setDateHeader("Expires", 0); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/webapp/assets/js/vendor/counterup.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /*========================= 4 | CounterUp 5 | ============================*/ 6 | /*! 7 | * jquery.counterup.js 1.0 8 | * 9 | * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 10 | * Released under the GPL v2 License 11 | * 12 | * Date: Nov 26, 2013 13 | */ 14 | !function(t){"use strict";t.fn.counterUp=function(e){var n=t.extend({time:400,delay:10},e);return this.each(function(){var e=t(this),u=n,a=function(){var t=[],n=u.time/u.delay,a=e.text(),r=/[0-9]+,[0-9]+/.test(a);a=a.replace(/,/g,"");for(var o=(/^[0-9]+$/.test(a),/^[0-9]+\.[0-9]+$/.test(a)),c=o?(a.split(".")[1]||[]).length:0,s=n;s>=1;s--){var d=parseInt(a/n*s);if(o&&(d=parseFloat(a/n*s).toFixed(c)),r)for(;/(\d+)(\d{3})/.test(d.toString());)d=d.toString().replace(/(\d+)(\d{3})/,"$1,$2");t.unshift(d)}e.data("counterup-nums",t),e.text("0");var i=function(){e.data("counterup-nums")&&(e.text(e.data("counterup-nums").shift()),e.data("counterup-nums").length?setTimeout(e.data("counterup-func"),u.delay):(delete e.data("counterup-nums"),e.data("counterup-nums",null),e.data("counterup-func",null)))};e.data("counterup-func",i),setTimeout(e.data("counterup-func"),u.delay)};e.waypoint(a,{offset:"100%",triggerOnce:!0})})}}(jQuery); 15 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/validation/Validator.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.validation; 2 | 3 | public class Validator { 4 | public static final String EMAIL_VALIDATION = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; 5 | public static final String PASSWORD_VALIDATION = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&-+=()])(?=\\S+$).{8,20}$"; 6 | public static final String MOBILE_VALIDATION = "^(0{1})(7{1})([0|1|2|4|5|6|7|8]{1})([0-9]{7})"; 7 | public static final String VERIFICATION_CODE_VALIDATION = "\\d{6}"; // ^[0-9]{6}$ 8 | public static final String POSTAL_CODE_VALIDATION = "\\d{5}"; // ^[0-9]{6}$ 9 | public static final String IS_INTEGER = "^\\d+$"; 10 | public static final String NON_DIGIT_PATTERN = "\\D+"; // retrieve integer value from order id (#00025 -> 25) 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Cart.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | public class Cart implements Serializable { 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.IDENTITY) 11 | private int id; 12 | 13 | 14 | @Column(nullable = false) 15 | private int qty; 16 | 17 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 18 | @JoinColumn(name = "user_id") 19 | private User user; 20 | 21 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 22 | @JoinColumn(name = "stock_id") 23 | private Stock stock; 24 | 25 | public int getId() { 26 | return id; 27 | } 28 | 29 | public void setId(int id) { 30 | this.id = id; 31 | } 32 | 33 | public int getQty() { 34 | return qty; 35 | } 36 | 37 | public void setQty(int qty) { 38 | this.qty = qty; 39 | } 40 | 41 | public User getUser() { 42 | return user; 43 | } 44 | 45 | public void setUser(User user) { 46 | this.user = user; 47 | } 48 | 49 | public Stock getStock() { 50 | return stock; 51 | } 52 | 53 | public void setStock(Stock stock) { 54 | this.stock = stock; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/webapp/assets/js/vendor/jquery.ui.touch-punch.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI Touch Punch 0.2.3 3 | * 4 | * Copyright 2011–2014, Dave Furfero 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * 7 | * Depends: 8 | * jquery.ui.widget.js 9 | * jquery.ui.mouse.js 10 | */ 11 | !function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/middleware/AuthFilter.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.middleware; 2 | 3 | import jakarta.annotation.Priority; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpSession; 6 | import jakarta.ws.rs.Priorities; 7 | import jakarta.ws.rs.container.ContainerRequestContext; 8 | import jakarta.ws.rs.container.ContainerRequestFilter; 9 | import jakarta.ws.rs.core.Context; 10 | import jakarta.ws.rs.core.Response; 11 | import jakarta.ws.rs.ext.Provider; 12 | import lk.jiat.smarttrade.annotation.IsUser; 13 | import lk.jiat.smarttrade.util.Env; 14 | 15 | import java.io.IOException; 16 | import java.net.URI; 17 | 18 | @Provider 19 | @Priority(Priorities.AUTHENTICATION) 20 | @IsUser 21 | public class AuthFilter implements ContainerRequestFilter { 22 | @Context 23 | private HttpServletRequest request; 24 | 25 | @Override 26 | public void filter(ContainerRequestContext containerRequestContext) throws IOException { 27 | HttpSession httpSession = request.getSession(false); 28 | System.out.println(request.getContextPath()); 29 | if (httpSession == null || httpSession.getAttribute("user") == null) { 30 | containerRequestContext 31 | .abortWith(Response.status(Response.Status.TEMPORARY_REDIRECT) 32 | .location(URI.create(request.getContextPath() + "/sign-in.html")).build()); 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/api/CheckoutController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller.api; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | import jakarta.ws.rs.*; 5 | import jakarta.ws.rs.core.Context; 6 | import jakarta.ws.rs.core.MediaType; 7 | import jakarta.ws.rs.core.Response; 8 | import lk.jiat.smarttrade.annotation.IsUser; 9 | import lk.jiat.smarttrade.dto.CheckoutRequestDTO; 10 | import lk.jiat.smarttrade.service.CheckoutService; 11 | import lk.jiat.smarttrade.util.AppUtil; 12 | 13 | @Path("/checkout") 14 | public class CheckoutController { 15 | @IsUser 16 | @GET 17 | @Path("/load-checkout-data") 18 | @Produces(MediaType.APPLICATION_JSON) 19 | public Response loadCheckoutData(@Context HttpServletRequest request) { 20 | String responseJson = new CheckoutService().loadCheckoutData(request); 21 | return Response.ok().entity(responseJson).build(); 22 | 23 | } 24 | 25 | 26 | @POST 27 | @Path("/checkout-process") 28 | @Consumes(MediaType.APPLICATION_JSON) 29 | @Produces(MediaType.APPLICATION_JSON) 30 | public Response processCheckout(String jsonData, @Context HttpServletRequest request) { 31 | CheckoutRequestDTO checkoutDTO = AppUtil.GSON.fromJson(jsonData, CheckoutRequestDTO.class); 32 | String responseJson = new CheckoutService().processCheckout(checkoutDTO, request); 33 | return Response.ok().entity(responseJson).build(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/DeliveryType.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | @Table(name = "delivery_types") 9 | @NamedQuery(name = "DeliveryType.findByName",query = "FROM DeliveryType dt WHERE dt.name=:name") 10 | public class DeliveryType implements Serializable { 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private int id; 14 | 15 | @Column(length = 50, nullable = false) 16 | private String name; 17 | 18 | @Column(nullable = false) 19 | private Double price; 20 | 21 | public int getId() { 22 | return id; 23 | } 24 | 25 | public void setId(int id) { 26 | this.id = id; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | public Double getPrice() { 38 | return price; 39 | } 40 | 41 | public void setPrice(Double price) { 42 | this.price = price; 43 | } 44 | 45 | public enum Value { 46 | WITHIN_CITY("Within City"), 47 | OUT_OF_CITY("Out of City"); 48 | private final String value; 49 | 50 | Value(String value) { 51 | this.value = value; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return this.value; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/Main.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade; 2 | 3 | import lk.jiat.smarttrade.config.AppConfig; 4 | import lk.jiat.smarttrade.listener.ContextPathListener; 5 | import org.apache.catalina.Context; 6 | import org.apache.catalina.LifecycleException; 7 | import org.apache.catalina.startup.Tomcat; 8 | import org.glassfish.jersey.servlet.ServletContainer; 9 | 10 | import java.io.File; 11 | 12 | public class Main { 13 | 14 | private static final int SERVER_PORT = 8080; 15 | private static final String CONTEXT_PATH = "/smarttrade"; 16 | 17 | public static void main(String[] args) { 18 | try { 19 | Tomcat tomcat = new Tomcat(); 20 | tomcat.setPort(SERVER_PORT); 21 | tomcat.getConnector(); 22 | 23 | Context context = tomcat.addWebapp(CONTEXT_PATH, new File("src/main/webapp").getAbsolutePath()); 24 | Tomcat.addServlet(context, "JerseyServlet", new ServletContainer(new AppConfig())); 25 | context.addServletMappingDecoded("/api/*", "JerseyServlet"); 26 | 27 | context.addApplicationListener(ContextPathListener.class.getName()); 28 | 29 | tomcat.start(); 30 | System.out.println("App URL: http://localhost:" + SERVER_PORT + CONTEXT_PATH); 31 | tomcat.getServer().await(); 32 | } catch (LifecycleException e) { 33 | throw new RuntimeException("Tomcat Embedded Server loading failed: " + e.getMessage()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/Test.java: -------------------------------------------------------------------------------- 1 | import lk.jiat.smarttrade.entity.Address; 2 | import lk.jiat.smarttrade.entity.Status; 3 | import lk.jiat.smarttrade.entity.User; 4 | import lk.jiat.smarttrade.mail.VerificationMail; 5 | import lk.jiat.smarttrade.provider.MailServiceProvider; 6 | import lk.jiat.smarttrade.util.AppUtil; 7 | import lk.jiat.smarttrade.util.HibernateUtil; 8 | import lk.jiat.smarttrade.validation.Validator; 9 | import org.hibernate.Session; 10 | import org.hibernate.SessionFactory; 11 | import org.hibernate.Transaction; 12 | 13 | import java.util.ArrayList; 14 | 15 | public class Test { 16 | public static void main(String[] args) { 17 | // 18 | // MailServiceProvider.getInstance().start(); 19 | // VerificationMail verificationMail = new VerificationMail("anjana.jiat@gmail.com", "123456"); 20 | // MailServiceProvider.getInstance().sendMail(verificationMail); 21 | 22 | // SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); 23 | // String s = AppUtil.generateCode(); 24 | // System.out.println(s); 25 | // try (Session s = HibernateUtil.getSessionFactory().openSession()) { 26 | // User user = s.createQuery("FROM User u WHERE u.id=:x", User.class) 27 | // .setParameter("x", 3) 28 | // .getSingleResult(); 29 | // 30 | // 31 | // } 32 | String orderCode = "Order25"; 33 | 34 | int orderId = Integer.parseInt(orderCode.replaceAll(Validator.NON_DIGIT_PATTERN, "")); 35 | System.out.println(orderId); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/OrderItem.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | @Table(name = "order_items") 9 | public class OrderItem implements Serializable { 10 | @Id 11 | @GeneratedValue(strategy = GenerationType.IDENTITY) 12 | private int id; 13 | 14 | @Column(nullable = false) 15 | private int qty; 16 | 17 | @Column(nullable = false) 18 | private int rating; 19 | 20 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 21 | @JoinColumn(name = "orders_id") 22 | private Order order; 23 | 24 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 25 | @JoinColumn(name = "stock_id") 26 | private Stock stock; 27 | 28 | public void setStock(Stock stock) { 29 | this.stock = stock; 30 | } 31 | 32 | public Stock getStock() { 33 | return stock; 34 | } 35 | 36 | public int getId() { 37 | return id; 38 | } 39 | 40 | public void setId(int id) { 41 | this.id = id; 42 | } 43 | 44 | public int getQty() { 45 | return qty; 46 | } 47 | 48 | public void setQty(int qty) { 49 | this.qty = qty; 50 | } 51 | 52 | public int getRating() { 53 | return rating; 54 | } 55 | 56 | public void setRating(int rating) { 57 | this.rating = rating; 58 | } 59 | 60 | public Order getOrder() { 61 | return order; 62 | } 63 | 64 | public void setOrder(Order order) { 65 | this.order = order; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/webapp/assets/js/verify-account.js: -------------------------------------------------------------------------------- 1 | let params = new URLSearchParams(window.location.search); 2 | 3 | const verificationCode = document.getElementById("verificationCode"); 4 | verificationCode.value = params.get("verificationCode"); 5 | const userEmail = params.get("email"); 6 | 7 | async function verifyAccount() { 8 | Notiflix.Loading.pulse("Wait...", { 9 | clickToClose: false, 10 | svgColor: '#0284c7' 11 | }); 12 | 13 | const verifyObj={ 14 | email:userEmail, 15 | verificationCode:verificationCode.value 16 | } 17 | try { 18 | const response = await fetch("api/verify-accounts",{ 19 | method:"POST", 20 | headers:{ 21 | "Content-Type":"application/json" 22 | }, 23 | body:JSON.stringify(verifyObj) 24 | }); 25 | 26 | if (response.ok) { 27 | const data = await response.json(); 28 | if (data.status) { 29 | Notiflix.Report.success( 30 | 'SmartTrade', 31 | data.message, 32 | 'Okay', // button title 33 | () => { 34 | window.location = "sign-in.html" 35 | }, 36 | ); 37 | 38 | } else { 39 | Notiflix.Notify.failure(data.message); 40 | } 41 | } else { 42 | Notiflix.Notify.failure("Verification process failed!"); 43 | } 44 | } catch (e) { 45 | Notiflix.Notify.failure(e); 46 | }finally { 47 | Notiflix.Loading.remove(1000); 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/webapp/assets/js/sign-in.js: -------------------------------------------------------------------------------- 1 | async function signIn() { 2 | Notiflix.Loading.pulse("Wait...", { 3 | clickToClose: false, 4 | svgColor: '#0284c7' 5 | }); 6 | 7 | let email = document.getElementById("email"); 8 | let password = document.getElementById("password"); 9 | 10 | const userLoginObj = { 11 | email: email.value, 12 | password: password.value 13 | } 14 | 15 | try { 16 | const response = await fetch("api/users/login", { 17 | method: "POST", 18 | headers: { 19 | "Content-Type": "application/json" 20 | }, 21 | body: JSON.stringify(userLoginObj) 22 | }); 23 | 24 | 25 | if (response.ok) { 26 | const data = await response.json(); 27 | if(data.status){ 28 | Notiflix.Report.success( 29 | 'SmartTrade', 30 | data.message, 31 | 'Okay', // button title 32 | () => { 33 | window.location = "index.html" 34 | }, 35 | ); 36 | 37 | }else{ 38 | Notiflix.Notify.failure(data.message,{ 39 | position:'center-top' 40 | }); 41 | } 42 | } else { 43 | Notiflix.Notify.failure("Login failed! Please try again",{ 44 | position:'center-top' 45 | }); 46 | } 47 | } catch (e) { 48 | Notiflix.Notify.failure(e.message,{ 49 | position:'center-top' 50 | }); 51 | }finally { 52 | Notiflix.Loading.remove(1000); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/CheckoutDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | public class CheckoutDTO implements Serializable { 7 | private boolean status; 8 | private String message; 9 | 10 | private UserAddressDTO userAddress; // optional 11 | private List cityList; 12 | private List cartList; 13 | private List deliveryTypes; 14 | 15 | public boolean isStatus() { 16 | return status; 17 | } 18 | 19 | public void setStatus(boolean status) { 20 | this.status = status; 21 | } 22 | 23 | public String getMessage() { 24 | return message; 25 | } 26 | 27 | public void setMessage(String message) { 28 | this.message = message; 29 | } 30 | 31 | public UserAddressDTO getUserAddress() { 32 | return userAddress; 33 | } 34 | 35 | public void setUserAddress(UserAddressDTO userAddress) { 36 | this.userAddress = userAddress; 37 | } 38 | 39 | public List getCityList() { 40 | return cityList; 41 | } 42 | 43 | public void setCityList(List cityList) { 44 | this.cityList = cityList; 45 | } 46 | 47 | public List getCartList() { 48 | return cartList; 49 | } 50 | 51 | public void setCartList(List cartList) { 52 | this.cartList = cartList; 53 | } 54 | 55 | public List getDeliveryTypes() { 56 | return deliveryTypes; 57 | } 58 | 59 | public void setDeliveryTypes(List deliveryTypes) { 60 | this.deliveryTypes = deliveryTypes; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/api/CartController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller.api; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | import jakarta.ws.rs.GET; 5 | import jakarta.ws.rs.Path; 6 | import jakarta.ws.rs.Produces; 7 | import jakarta.ws.rs.QueryParam; 8 | import jakarta.ws.rs.core.Context; 9 | import jakarta.ws.rs.core.MediaType; 10 | import jakarta.ws.rs.core.Response; 11 | import lk.jiat.smarttrade.service.CartService; 12 | import lk.jiat.smarttrade.service.ProductService; 13 | 14 | @Path("/user-carts") 15 | public class CartController { 16 | @Path("/cart") 17 | @GET 18 | @Produces(MediaType.APPLICATION_JSON) 19 | public Response addToCart( 20 | @QueryParam("productId") String prId, 21 | @QueryParam("qty") String qty, 22 | @Context HttpServletRequest request) { 23 | 24 | String responseJson = new CartService().addToCart(prId, qty, request); 25 | return Response.ok().entity(responseJson).build(); 26 | } 27 | 28 | @Path("/load-cart") 29 | @GET 30 | @Produces(MediaType.APPLICATION_JSON) 31 | public Response loadCartItems(@Context HttpServletRequest request) { 32 | String responseJson = new CartService().getLoadCartItems(request); 33 | return Response.ok().entity(responseJson).build(); 34 | } 35 | 36 | @GET // Changed from @DELETE 37 | @Path("/remove") 38 | @Produces(MediaType.APPLICATION_JSON) 39 | public Response removeCartItem(@QueryParam("cartItemId") int cartId, @Context HttpServletRequest request) { 40 | String responseJson = new CartService().removeCartItem(cartId, request); 41 | return Response.ok(responseJson).build(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Order.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | @Entity 9 | @Table(name = "orders") 10 | public class Order extends BaseEntity { 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private int id; 14 | 15 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 16 | @JoinColumn(name = "delivery_types_id") 17 | private DeliveryType deliveryType; 18 | 19 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 20 | @JoinColumn(name = "status_id") 21 | private Status status; 22 | 23 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 24 | @JoinColumn(name = "user_id") 25 | private User user; 26 | 27 | @OneToMany(mappedBy = "order") 28 | private Set orderItems = new HashSet<>(); 29 | 30 | public Set getOrderItems() { 31 | return orderItems; 32 | } 33 | 34 | public int getId() { 35 | return id; 36 | } 37 | 38 | public void setId(int id) { 39 | this.id = id; 40 | } 41 | 42 | public DeliveryType getDeliveryType() { 43 | return deliveryType; 44 | } 45 | 46 | public void setDeliveryType(DeliveryType deliveryType) { 47 | this.deliveryType = deliveryType; 48 | } 49 | 50 | public Status getStatus() { 51 | return status; 52 | } 53 | 54 | public void setStatus(Status status) { 55 | this.status = status; 56 | } 57 | 58 | public User getUser() { 59 | return user; 60 | } 61 | 62 | public void setUser(User user) { 63 | this.user = user; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/api/PaymentGatewayController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller.api; 2 | 3 | import jakarta.ws.rs.*; 4 | import jakarta.ws.rs.core.MediaType; 5 | import jakarta.ws.rs.core.MultivaluedMap; 6 | import jakarta.ws.rs.core.Response; 7 | import lk.jiat.smarttrade.service.OrderService; 8 | import lk.jiat.smarttrade.util.Env; 9 | import lk.jiat.smarttrade.util.PayHereUtil; 10 | 11 | import java.net.URI; 12 | 13 | @Path("/payments") 14 | public class PaymentGatewayController { 15 | @Path("/return") 16 | @GET 17 | public Response paymentSuccess(@QueryParam("orderId)") String orderId) { 18 | return Response.seeOther( 19 | URI.create(Env.get("app.url") + "/invoice.html?orderId=" + orderId) 20 | ).build(); 21 | } 22 | 23 | @Path("/cancel") 24 | @GET 25 | public Response paymentCancel() { 26 | System.out.println("cancel"); 27 | return Response.ok().build(); 28 | } 29 | 30 | @POST 31 | @Path("/notify") 32 | @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 33 | public Response notify(MultivaluedMap form) { 34 | 35 | String orderId = form.getFirst("order_id"); 36 | String statusCode = form.getFirst("status_code"); 37 | 38 | if (!PayHereUtil.validateNotify(form)) { 39 | return Response.status(400).entity("INVALID SIGNATURE").build(); 40 | } 41 | OrderService orderService = new OrderService(); 42 | if ("2".equals(statusCode)) { // 2 = SUCCESS 43 | orderService.completeOrder(orderId); 44 | } else { 45 | orderService.failOrder(orderId); 46 | } 47 | 48 | return Response.ok("OK").build(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/api/ProfileController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller.api; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | import jakarta.ws.rs.*; 5 | import jakarta.ws.rs.core.Context; 6 | import jakarta.ws.rs.core.MediaType; 7 | import jakarta.ws.rs.core.Response; 8 | import lk.jiat.smarttrade.annotation.IsUser; 9 | import lk.jiat.smarttrade.dto.UserDTO; 10 | import lk.jiat.smarttrade.service.ProfileService; 11 | import lk.jiat.smarttrade.util.AppUtil; 12 | 13 | @Path("/profiles") 14 | public class ProfileController { 15 | @IsUser 16 | @Path("/addresses") 17 | @GET 18 | @Produces(MediaType.APPLICATION_JSON) 19 | public Response loadAddresses(@Context HttpServletRequest request) { 20 | String responseJson = new ProfileService().loadUserAddresses(request); 21 | return Response.ok().entity(responseJson).build(); 22 | } 23 | 24 | @IsUser 25 | @Path("/update-profile") 26 | @PUT 27 | @Consumes(MediaType.APPLICATION_JSON) 28 | @Produces(MediaType.APPLICATION_JSON) 29 | public Response updateUserProfile(String jsonData, @Context HttpServletRequest request) { 30 | UserDTO userDTO = AppUtil.GSON.fromJson(jsonData, UserDTO.class); 31 | String responseJson = new ProfileService().updateProfile(userDTO, request); 32 | return Response.ok().entity(responseJson).build(); 33 | } 34 | 35 | @IsUser 36 | @Path("/user-profile") 37 | @GET 38 | @Produces(MediaType.APPLICATION_JSON) 39 | public Response loadUserProfile(@Context HttpServletRequest request) { 40 | String responseJson = new ProfileService().userProfile(request); 41 | return Response.ok().entity(responseJson).build(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/webapp/assets/js/sign-up.js: -------------------------------------------------------------------------------- 1 | async function signUp() { 2 | Notiflix.Loading.pulse("Wait...", { 3 | clickToClose: false, 4 | svgColor: '#0284c7' 5 | }); 6 | 7 | 8 | let firstName = document.getElementById("firstName"); 9 | let lastName = document.getElementById("lastName"); 10 | let email = document.getElementById("email"); 11 | let password = document.getElementById("password"); 12 | 13 | const user = { 14 | firstName: firstName.value, 15 | lastName: lastName.value, 16 | email: email.value, 17 | password: password.value 18 | } 19 | try { 20 | const response = await fetch("api/users", { 21 | method: "POST", 22 | headers: { 23 | "Content-Type": "application/json" 24 | }, 25 | body: JSON.stringify(user) 26 | }); 27 | 28 | 29 | if (response.ok) { // 200 30 | const data = await response.json(); 31 | if (data.status) { 32 | Notiflix.Report.success( 33 | 'SmartTrade', 34 | data.message, 35 | 'Okay' 36 | ); 37 | } else { 38 | Notiflix.Notify.failure(data.message,{ 39 | position:'center-top' 40 | }); 41 | } 42 | } else { 43 | Notiflix.Notify.failure('Something went wrong. Please check your credentials',{ 44 | position:'center-top' 45 | }); 46 | } 47 | } catch (e) { 48 | Notiflix.Notify.failure(e.message,{ 49 | position:'center-top' 50 | }); 51 | }finally { 52 | Notiflix.Loading.remove(1000); 53 | } 54 | } -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Discount.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | 8 | @Entity 9 | @NamedQuery(name = "Discount.findDefault", 10 | query = "FROM Discount d WHERE d.couponCode='DEFAULT'") 11 | public class Discount implements Serializable { 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.IDENTITY) 14 | private int id; 15 | 16 | @Column(name = "coupon_code", length = 45, nullable = false, unique = true) 17 | private String couponCode; 18 | 19 | @Column(nullable = false) 20 | private Double value; 21 | 22 | @Column(name = "started_at", nullable = false) 23 | private Date startedAt; 24 | 25 | @Column(name = "expired_at", nullable = false) 26 | private Date expiredAt; 27 | 28 | public int getId() { 29 | return id; 30 | } 31 | 32 | public void setId(int id) { 33 | this.id = id; 34 | } 35 | 36 | public String getCouponCode() { 37 | return couponCode; 38 | } 39 | 40 | public void setCouponCode(String couponCode) { 41 | this.couponCode = couponCode; 42 | } 43 | 44 | public Double getValue() { 45 | return value; 46 | } 47 | 48 | public void setValue(Double value) { 49 | this.value = value; 50 | } 51 | 52 | public Date getStartedAt() { 53 | return startedAt; 54 | } 55 | 56 | public void setStartedAt(Date startedAt) { 57 | this.startedAt = startedAt; 58 | } 59 | 60 | public Date getExpiredAt() { 61 | return expiredAt; 62 | } 63 | 64 | public void setExpiredAt(Date expiredAt) { 65 | this.expiredAt = expiredAt; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/UserAddressDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | public class UserAddressDTO { 4 | private int id; 5 | private String lineOne; 6 | private String lineTwo; 7 | private String postalCode; 8 | private String mobile; 9 | private boolean primary; 10 | private CityDTO city; 11 | private UserDTO user; 12 | 13 | public CityDTO getCity() { 14 | return city; 15 | } 16 | 17 | public void setCity(CityDTO city) { 18 | this.city = city; 19 | } 20 | 21 | public UserDTO getUser() { 22 | return user; 23 | } 24 | 25 | public void setUser(UserDTO user) { 26 | this.user = user; 27 | } 28 | 29 | public int getId() { 30 | return id; 31 | } 32 | 33 | public void setId(int id) { 34 | this.id = id; 35 | } 36 | 37 | public String getLineOne() { 38 | return lineOne; 39 | } 40 | 41 | public void setLineOne(String lineOne) { 42 | this.lineOne = lineOne; 43 | } 44 | 45 | public String getLineTwo() { 46 | return lineTwo; 47 | } 48 | 49 | public void setLineTwo(String lineTwo) { 50 | this.lineTwo = lineTwo; 51 | } 52 | 53 | public String getPostalCode() { 54 | return postalCode; 55 | } 56 | 57 | public void setPostalCode(String postalCode) { 58 | this.postalCode = postalCode; 59 | } 60 | 61 | public String getMobile() { 62 | return mobile; 63 | } 64 | 65 | public void setMobile(String mobile) { 66 | this.mobile = mobile; 67 | } 68 | 69 | public boolean isPrimary() { 70 | return primary; 71 | } 72 | 73 | public void setPrimary(boolean primary) { 74 | this.primary = primary; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Stock.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | @Entity 6 | public class Stock extends BaseEntity{ 7 | @Id 8 | @GeneratedValue(strategy = GenerationType.IDENTITY) 9 | private int id; 10 | 11 | @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY) 12 | @JoinColumn(name = "product_id") 13 | private Product product; 14 | 15 | @Column(nullable = false) 16 | private double price; 17 | 18 | @Column(nullable = false) 19 | private int qty; 20 | 21 | @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER) 22 | @JoinColumn(name = "discount_id") 23 | private Discount discount; 24 | 25 | @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER) 26 | @JoinColumn(name = "status_id") 27 | private Status status; 28 | 29 | public int getId() { 30 | return id; 31 | } 32 | 33 | public void setId(int id) { 34 | this.id = id; 35 | } 36 | 37 | public Product getProduct() { 38 | return product; 39 | } 40 | 41 | public void setProduct(Product product) { 42 | this.product = product; 43 | } 44 | 45 | public double getPrice() { 46 | return price; 47 | } 48 | 49 | public void setPrice(double price) { 50 | this.price = price; 51 | } 52 | 53 | public int getQty() { 54 | return qty; 55 | } 56 | 57 | public void setQty(int qty) { 58 | this.qty = qty; 59 | } 60 | 61 | public Discount getDiscount() { 62 | return discount; 63 | } 64 | 65 | public void setDiscount(Discount discount) { 66 | this.discount = discount; 67 | } 68 | 69 | public Status getStatus() { 70 | return status; 71 | } 72 | 73 | public void setStatus(Status status) { 74 | this.status = status; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/mail/Mailable.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.mail; 2 | 3 | import io.rocketbase.mail.EmailTemplateBuilder; 4 | import jakarta.mail.Message; 5 | import jakarta.mail.MessagingException; 6 | import jakarta.mail.Session; 7 | import jakarta.mail.Transport; 8 | import jakarta.mail.internet.InternetAddress; 9 | import jakarta.mail.internet.MimeMessage; 10 | import lk.jiat.smarttrade.provider.MailServiceProvider; 11 | import lk.jiat.smarttrade.util.Env; 12 | 13 | public abstract class Mailable implements Runnable { 14 | private final MailServiceProvider mailServiceProvider; 15 | private final EmailTemplateBuilder.EmailTemplateConfigBuilder emailTemplateConfigBuilder; 16 | 17 | public Mailable() { 18 | this.mailServiceProvider = MailServiceProvider.getInstance(); 19 | this.emailTemplateConfigBuilder = EmailTemplateBuilder.builder(); 20 | } 21 | 22 | @Override 23 | public void run() { 24 | try { 25 | Session mailSession = Session.getInstance(mailServiceProvider.getProperties(), mailServiceProvider.getAuthenticator()); 26 | MimeMessage mimeMessage = new MimeMessage(mailSession); 27 | mimeMessage.setFrom(new InternetAddress(Env.get("app.mail"))); 28 | build(mimeMessage); 29 | if (mimeMessage.getRecipients(Message.RecipientType.TO).length > 0) { 30 | Transport.send(mimeMessage); 31 | System.out.println("\u001B[32mEmail sending successful...\u001B[32m"); 32 | } else { 33 | throw new RuntimeException("Email recipients can not be empty..."); 34 | } 35 | } catch (MessagingException e) { 36 | throw new RuntimeException(e); 37 | } 38 | } 39 | 40 | public abstract void build(Message message) throws MessagingException; 41 | 42 | public EmailTemplateBuilder.EmailTemplateConfigBuilder getEmailTemplateBuilder(){ 43 | return emailTemplateConfigBuilder; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/CheckoutRequestDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | public class CheckoutRequestDTO implements Serializable { 6 | private boolean isCurrentAddress; 7 | private String firstName; 8 | private String lastName; 9 | private String citySelect; 10 | private String lineOne; 11 | private String lineTwo; 12 | private String postalCode; 13 | private String mobile; 14 | 15 | public boolean isCurrentAddress() { 16 | return isCurrentAddress; 17 | } 18 | 19 | public void setCurrentAddress(boolean currentAddress) { 20 | isCurrentAddress = currentAddress; 21 | } 22 | 23 | public String getFirstName() { 24 | return firstName; 25 | } 26 | 27 | public void setFirstName(String firstName) { 28 | this.firstName = firstName; 29 | } 30 | 31 | public String getLastName() { 32 | return lastName; 33 | } 34 | 35 | public void setLastName(String lastName) { 36 | this.lastName = lastName; 37 | } 38 | 39 | public String getCitySelect() { 40 | return citySelect; 41 | } 42 | 43 | public void setCitySelect(String citySelect) { 44 | this.citySelect = citySelect; 45 | } 46 | 47 | public String getLineOne() { 48 | return lineOne; 49 | } 50 | 51 | public void setLineOne(String lineOne) { 52 | this.lineOne = lineOne; 53 | } 54 | 55 | public String getLineTwo() { 56 | return lineTwo; 57 | } 58 | 59 | public void setLineTwo(String lineTwo) { 60 | this.lineTwo = lineTwo; 61 | } 62 | 63 | public String getPostalCode() { 64 | return postalCode; 65 | } 66 | 67 | public void setPostalCode(String postalCode) { 68 | this.postalCode = postalCode; 69 | } 70 | 71 | public String getMobile() { 72 | return mobile; 73 | } 74 | 75 | public void setMobile(String mobile) { 76 | this.mobile = mobile; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/resources/hibernate.cfg.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | com.mysql.cj.jdbc.Driver 8 | org.hibernate.dialect.MySQLDialect 9 | jdbc:mysql://localhost:3306/smarttrade?useSSL=false&allowPublicKeyRetrieval=true 10 | root 11 | 050201@Dilhara 12 | update 13 | true 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | AuthAccessFilter 23 | lk.jiat.smarttrade.middleware.AuthAccessFilter 24 | 25 | 26 | AuthAccessFilter 27 | /sign-up.html 28 | 29 | 30 | AuthAccessFilter 31 | /sign-in.html 32 | 33 | 34 | AuthAccessFilter 35 | /verify-account.html 36 | 37 | 38 | 39 | AccessControlFilter 40 | lk.jiat.smarttrade.middleware.AccessControlFilter 41 | 42 | 43 | AccessControlFilter 44 | /my-account.html 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/mail/VerificationMail.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.mail; 2 | 3 | import io.rocketbase.mail.model.HtmlTextEmail; 4 | import jakarta.mail.Message; 5 | import jakarta.mail.MessagingException; 6 | import jakarta.mail.internet.InternetAddress; 7 | import lk.jiat.smarttrade.util.Env; 8 | 9 | public class VerificationMail extends Mailable { 10 | private final String to; 11 | private final String verificationCode; 12 | 13 | public VerificationMail(String to, String verificationCode) { 14 | this.to = to; 15 | this.verificationCode = verificationCode; 16 | } 17 | 18 | @Override 19 | public void build(Message message) throws MessagingException { 20 | message.setRecipient(Message.RecipientType.TO, new InternetAddress(to)); 21 | message.setSubject("Email Verification Code - " + Env.get("app.name")); 22 | 23 | 24 | String appURL = Env.get("app.url"); 25 | String verifyURL = appURL + "/verify-account.html?email=" + to + "&verificationCode=" + verificationCode; 26 | 27 | HtmlTextEmail htmlTextEmail = getEmailTemplateBuilder() 28 | .header() 29 | .logo("https://upload.wikimedia.org/wikipedia/commons/e/eb/SmartTradePI.png").logoHeight(40).and() 30 | .text("WELCOME " + to).h1().center().and() 31 | .text("Thanks for register in our website").center().and() 32 | .text("To verify your email please click on the button below.").center().and() 33 | .text("Your Verification Code: " + verificationCode).center().and() 34 | .button("Verify Your Email", verifyURL).blue().center().and() 35 | .text("If you have a any trouble please paste this link in your browser.").center().and() 36 | .html("" + verifyURL + "").and() 37 | .copyright(Env.get("app.name")).url(appURL).suffix(". All Rights Reserved").and() 38 | .build(); 39 | 40 | 41 | message.setContent(htmlTextEmail.getHtml(), "text/html; charset=utf-8"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/api/UserController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller.api; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonObject; 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import jakarta.servlet.http.HttpSession; 7 | import jakarta.ws.rs.*; 8 | import jakarta.ws.rs.core.Context; 9 | import jakarta.ws.rs.core.MediaType; 10 | import jakarta.ws.rs.core.Response; 11 | import lk.jiat.smarttrade.annotation.IsUser; 12 | import lk.jiat.smarttrade.dto.UserDTO; 13 | import lk.jiat.smarttrade.entity.User; 14 | import lk.jiat.smarttrade.service.UserService; 15 | import lk.jiat.smarttrade.util.AppUtil; 16 | 17 | @Path("/users") 18 | public class UserController { 19 | 20 | @IsUser 21 | @Path("/logout") 22 | @GET 23 | public Response logout(@Context HttpServletRequest request) { 24 | 25 | HttpSession httpSession = request.getSession(false); 26 | if (httpSession != null && httpSession.getAttribute("user") != null) { 27 | httpSession.invalidate(); 28 | return Response.status(Response.Status.OK).build(); 29 | } else { 30 | System.out.println("else"); 31 | return Response.status(Response.Status.BAD_REQUEST).build(); 32 | } 33 | } 34 | 35 | @POST 36 | @Consumes(MediaType.APPLICATION_JSON) 37 | @Produces(MediaType.APPLICATION_JSON) 38 | public Response createNewAccount(String jsonData) { 39 | UserDTO userDTO = AppUtil.GSON.fromJson(jsonData, UserDTO.class); 40 | String responseJson = new UserService().addNewUser(userDTO); 41 | return Response.ok().entity(responseJson).build(); 42 | } 43 | 44 | @Path("/login") 45 | @POST 46 | @Consumes(MediaType.APPLICATION_JSON) 47 | @Produces(MediaType.APPLICATION_JSON) 48 | public Response userLogin(String jsonData, @Context HttpServletRequest request) { 49 | UserDTO userDTO = AppUtil.GSON.fromJson(jsonData, UserDTO.class); 50 | String responseJson = new UserService().userLogin(userDTO, request); 51 | return Response.ok().entity(responseJson).build(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/webapp/assets/fonts/slick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by Fontastic.me 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/api/ContentController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller.api; 2 | 3 | import jakarta.ws.rs.GET; 4 | import jakarta.ws.rs.Path; 5 | import jakarta.ws.rs.PathParam; 6 | import jakarta.ws.rs.Produces; 7 | import jakarta.ws.rs.core.MediaType; 8 | import jakarta.ws.rs.core.Response; 9 | import lk.jiat.smarttrade.service.CityService; 10 | import lk.jiat.smarttrade.service.ContentService; 11 | 12 | @Path("/data") 13 | public class ContentController { 14 | @Path("/product-data") 15 | @GET 16 | @Produces(MediaType.APPLICATION_JSON) 17 | public Response loadProductData() { 18 | String responseJson = new ContentService().loadProductData(); 19 | return Response.ok().entity(responseJson).build(); 20 | } 21 | 22 | @Path("/new-arrivals") 23 | @GET 24 | @Produces(MediaType.APPLICATION_JSON) 25 | public Response loadNewArrivals() { 26 | String responseJson = new ContentService().loadNewArrivalProducts(); 27 | return Response.ok().entity(responseJson).build(); 28 | } 29 | 30 | @Path("/cities") 31 | @GET 32 | @Produces(MediaType.APPLICATION_JSON) 33 | public Response loadCities() { 34 | String loadAllCities = new CityService().loadAllCities(); 35 | return Response.ok().entity(loadAllCities).build(); 36 | } 37 | 38 | @Path("/brands") 39 | @GET 40 | @Produces(MediaType.APPLICATION_JSON) 41 | public Response loadBrands() { 42 | String responseJson = new ContentService().loadBrandDetails(); 43 | return Response.ok().entity(responseJson).build(); 44 | } 45 | 46 | @Path("/{brandId}/models") 47 | @GET 48 | @Produces(MediaType.APPLICATION_JSON) 49 | public Response loadModels(@PathParam("brandId") int id) { 50 | String responseJson = new ContentService().loadModelDetails(id); 51 | return Response.ok().entity(responseJson).build(); 52 | } 53 | 54 | @Path("/specifications") 55 | @GET 56 | @Produces(MediaType.APPLICATION_JSON) 57 | public Response loadSpecifications() { 58 | String responseJson = new ContentService().loadProductSpecifications(); 59 | return Response.ok().entity(responseJson).build(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Seller.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | @Entity 9 | public class Seller extends BaseEntity{ 10 | @Id 11 | @GeneratedValue(strategy = GenerationType.IDENTITY) 12 | private int id; 13 | 14 | @Column(name = "company_name", length = 200, nullable = false) 15 | private String companyName; 16 | 17 | @Column(name = "company_mobile", length = 10, nullable = false) 18 | private String companyMobile; 19 | 20 | @Column(name = "company_email", length = 100, nullable = false) 21 | private String companyEmail; 22 | 23 | @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 24 | @JoinColumn(name = "status_id") 25 | private Status status; 26 | 27 | @OneToOne(cascade = CascadeType.ALL) 28 | @JoinColumn(name = "user_id") 29 | private User user; 30 | 31 | @OneToMany(mappedBy = "seller") 32 | private Set products = new HashSet<>(); 33 | 34 | public Set getProducts() { 35 | return products; 36 | } 37 | 38 | public int getId() { 39 | return id; 40 | } 41 | 42 | public void setId(int id) { 43 | this.id = id; 44 | } 45 | 46 | public String getCompanyName() { 47 | return companyName; 48 | } 49 | 50 | public void setCompanyName(String companyName) { 51 | this.companyName = companyName; 52 | } 53 | 54 | public String getCompanyMobile() { 55 | return companyMobile; 56 | } 57 | 58 | public void setCompanyMobile(String companyMobile) { 59 | this.companyMobile = companyMobile; 60 | } 61 | 62 | public String getCompanyEmail() { 63 | return companyEmail; 64 | } 65 | 66 | public void setCompanyEmail(String companyEmail) { 67 | this.companyEmail = companyEmail; 68 | } 69 | 70 | public Status getStatus() { 71 | return status; 72 | } 73 | 74 | public void setStatus(Status status) { 75 | this.status = status; 76 | } 77 | 78 | public User getUser() { 79 | return user; 80 | } 81 | 82 | public void setUser(User user) { 83 | this.user = user; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/plugins/insertgallery.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | RTE_DefaultConfig.plugin_insertgallery = RTE_Plugin_InsertGallery; 4 | 5 | function RTE_Plugin_InsertGallery() { 6 | 7 | 8 | 9 | var obj = this; 10 | 11 | var config, editor; 12 | 13 | obj.PluginName = "InsertGallery"; 14 | 15 | obj.InitConfig = function (argconfig) { 16 | config = argconfig; 17 | } 18 | obj.InitEditor = function (argeditor) { 19 | editor = argeditor; 20 | 21 | editor.attachEvent("exec_command_insertgallery", function (state, cmd, value) { 22 | state.returnValue = true; 23 | obj.DoInsertGallery(); 24 | }); 25 | 26 | 27 | } 28 | 29 | function __Append(parent, tagname, csstext, cssclass) { 30 | var tag = parent.ownerDocument.createElement(tagname); 31 | if (csstext) tag.style.cssText = csstext; 32 | if (cssclass) tag.className = cssclass; 33 | parent.appendChild(tag); 34 | return tag; 35 | } 36 | 37 | obj.DoInsertGallery = function () { 38 | 39 | var dialoginner = editor.createDialog(editor.getLangText("insertgallerytitle"), "rte-dialog-insertgallery"); 40 | 41 | var scrollpanel = __Append(dialoginner, "rte-insertgallery-scrollpanel", "overflow-y:auto;padding-bottom:32px;"); 42 | var container = __Append(scrollpanel, "rte-insertgallery-container", "display:flex;flex-wrap:wrap;"); 43 | 44 | container.focus();//focus to let ESC key close dialog 45 | 46 | function CreateDiv(item) { 47 | var url, text; 48 | if (typeof (item) == "string") { 49 | url = item; 50 | } else if (item instanceof Array) { 51 | url = item[0]; 52 | text = item[1]; 53 | } 54 | else if (item && item.url) { 55 | url = item.url; 56 | text = item.text; 57 | } 58 | else { 59 | return; 60 | } 61 | 62 | var divitem = __Append(container, "rte-insertgallery-image-item", "cursor:pointer;width:128px;height:128px;margin:12px;box-shadow:0 0 8px #ccc;display:flex;align-items:center;justify-content:center;") 63 | var img = __Append(divitem, "img", "max-width:90%;max-height:90%;"); 64 | img.src = url; 65 | 66 | divitem.onclick = function () { 67 | editor.insertImageByUrl(url); 68 | dialoginner.close(); 69 | } 70 | } 71 | 72 | for (var i = 0; i < config.galleryImages.length; i++) { 73 | var item = config.galleryImages[i]; 74 | CreateDiv(item); 75 | } 76 | 77 | } 78 | } 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/main/webapp/assets/css/vendor/slick.css: -------------------------------------------------------------------------------- 1 | /* Slider */ 2 | .slick-slider { 3 | position: relative; 4 | 5 | display: block; 6 | box-sizing: border-box; 7 | 8 | -webkit-user-select: none; 9 | -moz-user-select: none; 10 | -ms-user-select: none; 11 | user-select: none; 12 | 13 | -webkit-touch-callout: none; 14 | -khtml-user-select: none; 15 | -ms-touch-action: pan-y; 16 | touch-action: pan-y; 17 | -webkit-tap-highlight-color: transparent; 18 | } 19 | 20 | .slick-list { 21 | position: relative; 22 | 23 | display: block; 24 | overflow: hidden; 25 | 26 | margin: 0; 27 | padding: 0; 28 | } 29 | 30 | .slick-list:focus { 31 | outline: none; 32 | } 33 | 34 | .slick-list.dragging { 35 | cursor: pointer; 36 | cursor: hand; 37 | } 38 | 39 | .slick-slider .slick-track, 40 | .slick-slider .slick-list { 41 | -webkit-transform: translate3d(0, 0, 0); 42 | -moz-transform: translate3d(0, 0, 0); 43 | -ms-transform: translate3d(0, 0, 0); 44 | -o-transform: translate3d(0, 0, 0); 45 | transform: translate3d(0, 0, 0); 46 | } 47 | 48 | .slick-track { 49 | position: relative; 50 | top: 0; 51 | left: 0; 52 | 53 | display: block; 54 | margin-left: auto; 55 | margin-right: auto; 56 | } 57 | 58 | .slick-track:before, 59 | .slick-track:after { 60 | display: table; 61 | 62 | content: ''; 63 | } 64 | 65 | .slick-track:after { 66 | clear: both; 67 | } 68 | 69 | .slick-loading .slick-track { 70 | visibility: hidden; 71 | } 72 | 73 | .slick-slide { 74 | display: none; 75 | float: left; 76 | 77 | height: 100%; 78 | min-height: 1px; 79 | } 80 | 81 | [dir='rtl'] .slick-slide { 82 | float: right; 83 | } 84 | 85 | .slick-slide img { 86 | display: block; 87 | } 88 | 89 | .slick-slide.slick-loading img { 90 | display: none; 91 | } 92 | 93 | .slick-slide.dragging img { 94 | pointer-events: none; 95 | } 96 | 97 | .slick-initialized .slick-slide { 98 | display: block; 99 | } 100 | 101 | .slick-loading .slick-slide { 102 | visibility: hidden; 103 | } 104 | 105 | .slick-vertical .slick-slide { 106 | display: block; 107 | 108 | height: auto; 109 | 110 | border: 1px solid transparent; 111 | } 112 | 113 | .slick-arrow.slick-hidden { 114 | display: none; 115 | } -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Address.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Entity 8 | public class Address implements Serializable { 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.IDENTITY) 11 | private int id; 12 | @Column(name = "line_one", length = 45, nullable = false) 13 | private String lineOne; 14 | @Column(name = "line_two", length = 45) 15 | private String lineTwo; 16 | @Column(name = "postal_code", length = 10) 17 | private String postalCode; 18 | @Column(length = 10, nullable = false) 19 | private String mobile; 20 | 21 | @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 22 | @JoinColumn(name = "city_id") 23 | private City city; 24 | 25 | @ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL) 26 | @JoinColumn(name = "user_id") 27 | private User user; 28 | 29 | @Column(name = "is_primary", nullable = false) 30 | private boolean isPrimary=false; 31 | 32 | public boolean isPrimary() { 33 | return isPrimary; 34 | } 35 | 36 | public void setPrimary(boolean primary) { 37 | isPrimary = primary; 38 | } 39 | 40 | public User getUser() { 41 | return user; 42 | } 43 | 44 | public void setUser(User user) { 45 | this.user = user; 46 | } 47 | 48 | public int getId() { 49 | return id; 50 | } 51 | 52 | public void setId(int id) { 53 | this.id = id; 54 | } 55 | 56 | public String getLineOne() { 57 | return lineOne; 58 | } 59 | 60 | public void setLineOne(String lineOne) { 61 | this.lineOne = lineOne; 62 | } 63 | 64 | public String getLineTwo() { 65 | return lineTwo; 66 | } 67 | 68 | public void setLineTwo(String lineTwo) { 69 | this.lineTwo = lineTwo; 70 | } 71 | 72 | public String getPostalCode() { 73 | return postalCode; 74 | } 75 | 76 | public void setPostalCode(String postalCode) { 77 | this.postalCode = postalCode; 78 | } 79 | 80 | public String getMobile() { 81 | return mobile; 82 | } 83 | 84 | public void setMobile(String mobile) { 85 | this.mobile = mobile; 86 | } 87 | 88 | public City getCity() { 89 | return city; 90 | } 91 | 92 | public void setCity(City city) { 93 | this.city = city; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/provider/MailServiceProvider.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.provider; 2 | 3 | import jakarta.mail.Authenticator; 4 | import jakarta.mail.PasswordAuthentication; 5 | import lk.jiat.smarttrade.mail.Mailable; 6 | import lk.jiat.smarttrade.util.Env; 7 | 8 | import java.util.Properties; 9 | import java.util.concurrent.BlockingQueue; 10 | import java.util.concurrent.LinkedBlockingQueue; 11 | import java.util.concurrent.ThreadPoolExecutor; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | public class MailServiceProvider { 15 | private ThreadPoolExecutor executor; 16 | private Authenticator authenticator; 17 | private final BlockingQueue blockingQueue = new LinkedBlockingQueue<>(); 18 | private final Properties properties = new Properties(); 19 | private static MailServiceProvider mailServiceProvider; 20 | 21 | private MailServiceProvider() { 22 | properties.put("mail.smtp.auth", true); 23 | properties.put("mail.smtp.starttls.enable", true); 24 | properties.put("mail.smtp.host", Env.get("mail.host")); 25 | properties.put("mail.smtp.port", Env.get("mail.port")); 26 | } 27 | 28 | public static MailServiceProvider getInstance() { 29 | if (mailServiceProvider == null) { 30 | mailServiceProvider = new MailServiceProvider(); 31 | } 32 | return mailServiceProvider; 33 | } 34 | 35 | public void start() { 36 | authenticator = new Authenticator() { 37 | @Override 38 | protected PasswordAuthentication getPasswordAuthentication() { 39 | return new PasswordAuthentication(Env.get("mail.username"), Env.get("mail.password")); 40 | } 41 | }; 42 | executor = new ThreadPoolExecutor(2, 5, 5, 43 | TimeUnit.SECONDS, blockingQueue, new ThreadPoolExecutor.AbortPolicy()); 44 | executor.prestartCoreThread(); 45 | System.out.println("\u001B[32mEmailServiceProvider Initialized...\u001B[32m"); 46 | } 47 | 48 | public Properties getProperties() { 49 | return properties; 50 | } 51 | 52 | public Authenticator getAuthenticator() { 53 | return authenticator; 54 | } 55 | 56 | public void shutdown() { 57 | if (executor != null) { 58 | executor.shutdown(); 59 | } 60 | } 61 | 62 | public void sendMail(Mailable mailable){ 63 | boolean offer = blockingQueue.offer(mailable); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/util/PayHereUtil.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.util; 2 | 3 | import jakarta.ws.rs.core.MultivaluedMap; 4 | 5 | import java.nio.charset.StandardCharsets; 6 | import java.security.MessageDigest; 7 | import java.security.NoSuchAlgorithmException; 8 | import java.util.Locale; 9 | 10 | public class PayHereUtil { 11 | private static final String MERCHANT_ID = ""; // replace with your merchant id 12 | private static final String MERCHANT_SECRET = ""; // replace with your merchant secret 13 | 14 | public static String getMerchantId() { 15 | return MERCHANT_ID; 16 | } 17 | 18 | public static String getMerchantSecret() { 19 | return MERCHANT_SECRET; 20 | } 21 | 22 | public static String generateHash(String orderId, double amount, String currency) { 23 | 24 | String formattedAmount = String.format(Locale.US, "%.2f", amount); 25 | 26 | String secretHash = md5(MERCHANT_SECRET).toUpperCase(); 27 | 28 | String raw = MERCHANT_ID 29 | + orderId 30 | + formattedAmount 31 | + currency 32 | + secretHash; 33 | 34 | return md5(raw).toUpperCase(); 35 | } 36 | 37 | public static boolean validateNotify(MultivaluedMap form) { 38 | 39 | String merchantId = form.getFirst("merchant_id"); 40 | String orderId = form.getFirst("order_id"); 41 | String amount = form.getFirst("payhere_amount"); 42 | String currency = form.getFirst("payhere_currency"); 43 | String statusCode = form.getFirst("status_code"); 44 | String receivedSig = form.getFirst("md5sig"); 45 | 46 | String localSig = md5( 47 | merchantId + 48 | orderId + 49 | amount + 50 | currency + 51 | statusCode + 52 | md5(MERCHANT_SECRET).toUpperCase() 53 | ).toUpperCase(); 54 | 55 | return localSig.equals(receivedSig); 56 | } 57 | 58 | private static String md5(String input) { 59 | try { 60 | MessageDigest md = MessageDigest.getInstance("MD5"); 61 | byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8)); 62 | 63 | StringBuilder sb = new StringBuilder(); 64 | for (byte b : digest) { 65 | sb.append(String.format("%02x", b)); 66 | } 67 | return sb.toString(); 68 | 69 | } catch (NoSuchAlgorithmException e) { 70 | throw new RuntimeException("MD5 error", e); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/plugins/samples/insertcode_v1.js: -------------------------------------------------------------------------------- 1 | 2 | if (!RTE_DefaultConfig.svgCode_insertcode) { 3 | RTE_DefaultConfig.svgCode_insertcode = ''; 4 | } 5 | 6 | RTE_DefaultConfig.plugin_insertcode = RTE_Plugin_InsertCode; 7 | 8 | function RTE_Plugin_InsertCode() { 9 | 10 | 11 | 12 | var obj = this; 13 | 14 | var config, editor; 15 | 16 | obj.PluginName = "InsertCode"; 17 | 18 | obj.InitConfig = function (argconfig) { 19 | config = argconfig; 20 | } 21 | obj.InitEditor = function (argeditor) { 22 | editor = argeditor; 23 | 24 | editor.attachEvent("exec_command_insertcode", function (state, cmd, value) { 25 | console.log(state, cmd, value); 26 | obj.DoInsertCode(); 27 | state.returnValue = true; 28 | }); 29 | 30 | editor.toolbarFactoryMap["insertcode"] = function (cmd) { 31 | console.log(cmd); 32 | var span = editor.createToolbarButton(cmd); 33 | span.style.backgroundColor = '' 34 | return span; 35 | }; 36 | 37 | } 38 | 39 | function __Append(parent, tagname, csstext, cssclass) { 40 | var tag = parent.ownerDocument.createElement(tagname); 41 | if (csstext) tag.style.cssText = csstext; 42 | if (cssclass) tag.className = cssclass; 43 | parent.appendChild(tag); 44 | return tag; 45 | } 46 | 47 | 48 | obj.DoInsertCode = function () { 49 | 50 | var dialoginner = editor.createDialog("InsertCode", "rte-dialog-insertcode"); 51 | 52 | var div1 = __Append(dialoginner, "div", "position:relative;text-align:center;"); 53 | var textarea = __Append(div1, "textarea", "width:300px;height:200px") 54 | 55 | var divfooter = __Append(dialoginner, "rte-dialog-footer",null,"rte-dialog-footer-center"); 56 | 57 | var btn = __Append(divfooter, "rte-dialog-button") 58 | btn.innerText = "Insert"; 59 | 60 | setTimeout(function () { 61 | textarea.focus(); 62 | }, 300); 63 | 64 | btn.onclick = function () { 65 | dialoginner.close(); 66 | var p = editor.insertRootParagraph() 67 | var ctag = __Append(p, "code"); 68 | ctag.innerText = textarea.value; 69 | editor.focus(); 70 | } 71 | } 72 | } 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/plugins/inserttemplate.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | RTE_DefaultConfig.plugin_inserttemplate = RTE_Plugin_InsertTemplate; 4 | 5 | function RTE_Plugin_InsertTemplate() { 6 | 7 | 8 | 9 | var obj = this; 10 | 11 | var config, editor; 12 | 13 | obj.PluginName = "InsertTemplate"; 14 | 15 | obj.InitConfig = function (argconfig) { 16 | config = argconfig; 17 | } 18 | obj.InitEditor = function (argeditor) { 19 | editor = argeditor; 20 | 21 | editor.attachEvent("exec_command_inserttemplate", function (state, cmd, value) { 22 | state.returnValue = true; 23 | obj.DoInsertTemplate(); 24 | }); 25 | 26 | 27 | } 28 | 29 | function __Append(parent, tagname, csstext, cssclass) { 30 | var tag = parent.ownerDocument.createElement(tagname); 31 | if (csstext) tag.style.cssText = csstext; 32 | if (cssclass) tag.className = cssclass; 33 | parent.appendChild(tag); 34 | return tag; 35 | } 36 | 37 | obj.DoInsertTemplate = function () { 38 | 39 | var dialoginner = editor.createDialog(editor.getLangText("inserttemplatetitle"), "rte-dialog-inserttemplate"); 40 | 41 | var scrollpanel = __Append(dialoginner, "rte-inserttemplate-scrollpanel", "overflow-y:auto;padding-bottom:32px;"); 42 | var container = __Append(scrollpanel, "rte-inserttemplate-container", "display:flex;flex-wrap:wrap;"); 43 | 44 | container.focus();//focus to let ESC key close dialog 45 | 46 | function CreateDiv(item) { 47 | var text = item[0]; 48 | var html = item[1]; 49 | console.log(item, text, html); 50 | 51 | var divitem = __Append(container, "rte-inserttemplate-image-item", "cursor:pointer;width:256px;height:256px;margin:12px;box-shadow:0 0 8px #ccc;display:flex;align-items:center;justify-content:center;") 52 | var div = __Append(divitem, "div", "max-width:90%;max-height:90%;overflow:auto;"); 53 | var innerdiv = __Append(div, "div"); 54 | innerdiv.innerHTML = html; 55 | div.title = text; 56 | 57 | var scale = Math.min(200 / div.scrollWidth, 200 / div.scrollHeight); 58 | if (scale < 1) { 59 | 60 | var tx, ty; 61 | tx = ty = (Math.max(div.scrollWidth, div.scrollHeight) - 200) / 2; 62 | innerdiv.style.transform = "scale(" + scale + ") translate(-" + tx + "px,-" + ty + "px)"; 63 | div.style.overflow = "hidden"; 64 | } 65 | 66 | divitem.onclick = function () { 67 | editor.setHTMLCode(html); 68 | dialoginner.close(); 69 | } 70 | } 71 | 72 | for (var i = 0; i < config.htmlTemplates.length; i++) { 73 | var item = config.htmlTemplates[i]; 74 | CreateDiv(item); 75 | } 76 | 77 | } 78 | } 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/User.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.util.HashSet; 6 | import java.util.LinkedHashSet; 7 | import java.util.Set; 8 | 9 | @Entity 10 | @Table(name = "users") 11 | @NamedQuery(name = "User.getByEmail", 12 | query = "FROM User u WHERE u.email=:email") 13 | public class User extends BaseEntity { 14 | @Id 15 | @GeneratedValue(strategy = GenerationType.IDENTITY) 16 | private int id; 17 | 18 | @Column(name = "first_name", nullable = false, length = 45) 19 | private String firstName; 20 | 21 | @Column(name = "last_name", nullable = false, length = 45) 22 | private String lastName; 23 | 24 | @Column(nullable = false, length = 150, unique = true) 25 | private String email; 26 | 27 | @Column(nullable = false, length = 20) 28 | private String password; 29 | 30 | @Column(name = "verification_code", nullable = false, length = 15) 31 | private String verificationCode; 32 | 33 | @ManyToOne(fetch = FetchType.LAZY) 34 | @JoinColumn(name = "status_id", nullable = false) 35 | private Status status; 36 | 37 | @OneToMany(mappedBy = "user") 38 | private Set
addresses = new HashSet<>(); 39 | 40 | @OneToMany(mappedBy = "user") 41 | private Set orders = new HashSet<>(); 42 | 43 | @OneToMany(mappedBy = "user") 44 | private Set carts = new HashSet<>(); 45 | 46 | public Set getCarts() { 47 | return carts; 48 | } 49 | 50 | public Set getOrders() { 51 | return orders; 52 | } 53 | 54 | public Set
getAddresses() { 55 | return addresses; 56 | } 57 | 58 | public int getId() { 59 | return id; 60 | } 61 | 62 | public void setId(int id) { 63 | this.id = id; 64 | } 65 | 66 | public String getFirstName() { 67 | return firstName; 68 | } 69 | 70 | public void setFirstName(String firstName) { 71 | this.firstName = firstName; 72 | } 73 | 74 | public String getLastName() { 75 | return lastName; 76 | } 77 | 78 | public void setLastName(String lastName) { 79 | this.lastName = lastName; 80 | } 81 | 82 | public String getEmail() { 83 | return email; 84 | } 85 | 86 | public void setEmail(String email) { 87 | this.email = email; 88 | } 89 | 90 | public String getPassword() { 91 | return password; 92 | } 93 | 94 | public void setPassword(String password) { 95 | this.password = password; 96 | } 97 | 98 | public String getVerificationCode() { 99 | return verificationCode; 100 | } 101 | 102 | public void setVerificationCode(String verificationCode) { 103 | this.verificationCode = verificationCode; 104 | } 105 | 106 | public Status getStatus() { 107 | return status; 108 | } 109 | 110 | public void setStatus(Status status) { 111 | this.status = status; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/webapp/assets/js/vendor/sal.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.sal=t():e.sal=t()}(this,(function(){return(()=>{"use strict";var e={855:(e,t,n)=>{function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;tE});var s="Sal was not initialised! Probably it is used in SSR.",i="Your browser does not support IntersectionObserver!\nGet a polyfill from here:\nhttps://github.com/w3c/IntersectionObserver/tree/master/polyfill",l={root:null,rootMargin:"0% 50%",threshold:.5,animateClassName:"sal-animate",disabledClassName:"sal-disabled",enterEventName:"sal:in",exitEventName:"sal:out",selector:"[data-sal]",once:!0,disabled:!1},c=[],u=null,d=function(e){e&&e!==l&&(l=o(o({},l),e))},f=function(e){e.classList.remove(l.animateClassName)},b=function(e,t){var n=new CustomEvent(e,{bubbles:!0,detail:t});t.target.dispatchEvent(n)},p=function(){document.body.classList.add(l.disabledClassName)},m=function(){u.disconnect(),u=null},v=function(){return l.disabled||"function"==typeof l.disabled&&l.disabled()},y=function(e,t){e.forEach((function(e){var n=e.target,r=void 0!==n.dataset.salRepeat,o=void 0!==n.dataset.salOnce,a=r||!(o||l.once);e.intersectionRatio>=l.threshold?(function(e){e.target.classList.add(l.animateClassName),b(l.enterEventName,e)}(e),a||t.unobserve(n)):a&&function(e){f(e.target),b(l.exitEventName,e)}(e)}))},O=function(){var e=[].filter.call(document.querySelectorAll(l.selector),(function(e){return!function(e){return e.classList.contains(l.animateClassName)}(e,l.animateClassName)}));return e.forEach((function(e){return u.observe(e)})),e},h=function(){p(),m()},g=function(){document.body.classList.remove(l.disabledClassName),u=new IntersectionObserver(y,{root:l.root,rootMargin:l.rootMargin,threshold:l.threshold}),c=O()},w=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};m(),Array.from(document.querySelectorAll(l.selector)).forEach(f),d(e),g()},j=function(){var e=O();c.push(e)};const E=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:l;if(d(e),"undefined"==typeof window)return console.warn(s),{elements:c,disable:h,enable:g,reset:w,update:j};if(!window.IntersectionObserver)throw p(),Error(i);return v()?p():g(),{elements:c,disable:h,enable:g,reset:w,update:j}}}},t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={exports:{}};return e[r](o,o.exports,n),o.exports}return n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n(855)})().default})); 2 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/CartDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | public class CartDTO implements Serializable { 7 | 8 | 9 | private Integer cartId; 10 | private int qty; 11 | private int stockId; 12 | private double price; 13 | private int availableQty; 14 | private double discount; 15 | private String status; 16 | 17 | private int productId; 18 | private String title; 19 | private String description; 20 | private List images; 21 | 22 | public CartDTO() { 23 | } 24 | 25 | public CartDTO(Integer cartId, int qty, int stockId, double price, int availableQty, double discount, String status, int productId, String title, String description, List images) { 26 | this.cartId = cartId; 27 | this.qty = qty; 28 | this.stockId = stockId; 29 | this.price = price; 30 | this.availableQty = availableQty; 31 | this.discount = discount; 32 | this.status = status; 33 | this.productId = productId; 34 | this.title = title; 35 | this.description = description; 36 | this.images = images; 37 | } 38 | 39 | public Integer getCartId() { 40 | return cartId; 41 | } 42 | 43 | public void setCartId(Integer cartId) { 44 | this.cartId = cartId; 45 | } 46 | 47 | public int getQty() { 48 | return qty; 49 | } 50 | 51 | public void setQty(int qty) { 52 | this.qty = qty; 53 | } 54 | 55 | public int getStockId() { 56 | return stockId; 57 | } 58 | 59 | public void setStockId(int stockId) { 60 | this.stockId = stockId; 61 | } 62 | 63 | public double getPrice() { 64 | return price; 65 | } 66 | 67 | public void setPrice(double price) { 68 | this.price = price; 69 | } 70 | 71 | public int getAvailableQty() { 72 | return availableQty; 73 | } 74 | 75 | public void setAvailableQty(int availableQty) { 76 | this.availableQty = availableQty; 77 | } 78 | 79 | public double getDiscount() { 80 | return discount; 81 | } 82 | 83 | public void setDiscount(double discount) { 84 | this.discount = discount; 85 | } 86 | 87 | public String getStatus() { 88 | return status; 89 | } 90 | 91 | public void setStatus(String status) { 92 | this.status = status; 93 | } 94 | 95 | public int getProductId() { 96 | return productId; 97 | } 98 | 99 | public void setProductId(int productId) { 100 | this.productId = productId; 101 | } 102 | 103 | public String getTitle() { 104 | return title; 105 | } 106 | 107 | public void setTitle(String title) { 108 | this.title = title; 109 | } 110 | 111 | public String getDescription() { 112 | return description; 113 | } 114 | 115 | public void setDescription(String description) { 116 | this.description = description; 117 | } 118 | 119 | public List getImages() { 120 | return images; 121 | } 122 | 123 | public void setImages(List images) { 124 | this.images = images; 125 | } 126 | 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/entity/Product.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.entity; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.HashSet; 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | @Entity 11 | public class Product extends BaseEntity { 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.IDENTITY) 14 | private int id; 15 | 16 | @Column(length = 200, nullable = false) 17 | private String title; 18 | 19 | @Column(nullable = false, columnDefinition = "TEXT") 20 | private String description; 21 | 22 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 23 | @JoinColumn(name = "model_id") 24 | private Model model; 25 | 26 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 27 | @JoinColumn(name = "color_id") 28 | private Color color; 29 | 30 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 31 | @JoinColumn(name = "quality_id") 32 | private Quality quality; 33 | 34 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 35 | @JoinColumn(name = "storage_id") 36 | private Storage storage; 37 | 38 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 39 | @JoinColumn(name = "seller_id") 40 | private Seller seller; 41 | 42 | @OneToMany(mappedBy = "product") 43 | private Set stocks = new HashSet<>(); 44 | 45 | @Column(name="images") 46 | @CollectionTable(name = "product_images",joinColumns = @JoinColumn(name = "pr_id")) 47 | @ElementCollection(fetch = FetchType.EAGER) 48 | private List images; 49 | 50 | 51 | public List getImages() { 52 | return images; 53 | } 54 | 55 | public void setImages(List images) { 56 | this.images = images; 57 | } 58 | 59 | public Set getStocks() { 60 | return stocks; 61 | } 62 | 63 | public int getId() { 64 | return id; 65 | } 66 | 67 | public void setId(int id) { 68 | this.id = id; 69 | } 70 | 71 | public String getTitle() { 72 | return title; 73 | } 74 | 75 | public void setTitle(String title) { 76 | this.title = title; 77 | } 78 | 79 | public String getDescription() { 80 | return description; 81 | } 82 | 83 | public void setDescription(String description) { 84 | this.description = description; 85 | } 86 | 87 | public Model getModel() { 88 | return model; 89 | } 90 | 91 | public void setModel(Model model) { 92 | this.model = model; 93 | } 94 | 95 | public Color getColor() { 96 | return color; 97 | } 98 | 99 | public void setColor(Color color) { 100 | this.color = color; 101 | } 102 | 103 | public Quality getQuality() { 104 | return quality; 105 | } 106 | 107 | public void setQuality(Quality quality) { 108 | this.quality = quality; 109 | } 110 | 111 | public Storage getStorage() { 112 | return storage; 113 | } 114 | 115 | public void setStorage(Storage storage) { 116 | this.storage = storage; 117 | } 118 | 119 | public Seller getSeller() { 120 | return seller; 121 | } 122 | 123 | public void setSeller(Seller seller) { 124 | this.seller = seller; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/lang/rte-lang.js: -------------------------------------------------------------------------------- 1 | [{"lang":"af","name":"Afrikaans","desc":"Afrikaans"},{"lang":"ar","name":"Arabic","desc":"العربية"},{"lang":"bg","name":"Bulgarian","desc":"Български"},{"lang":"bn","name":"Bangla","desc":"বাংলা"},{"lang":"bs","name":"Bosnian","desc":"bosanski (latinica)"},{"lang":"ca","name":"Catalan","desc":"Català"},{"lang":"cs","name":"Czech","desc":"Čeština"},{"lang":"cy","name":"Welsh","desc":"Welsh"},{"lang":"da","name":"Danish","desc":"Dansk"},{"lang":"de","name":"German","desc":"Deutsch"},{"lang":"el","name":"Greek","desc":"Ελληνικά"},{"lang":"es","name":"Spanish","desc":"Español"},{"lang":"et","name":"Estonian","desc":"Eesti"},{"lang":"fa","name":"Persian","desc":"Persian"},{"lang":"fi","name":"Finnish","desc":"Suomi"},{"lang":"fil","name":"Filipino","desc":"Filipino"},{"lang":"fj","name":"Fijian","desc":"Fijian"},{"lang":"fr","name":"French","desc":"Français"},{"lang":"ga","name":"Irish","desc":"Gaeilge"},{"lang":"gu","name":"Gujarati","desc":"ગુજરાતી"},{"lang":"he","name":"Hebrew","desc":"עברית"},{"lang":"hi","name":"Hindi","desc":"हिंदी"},{"lang":"hr","name":"Croatian","desc":"Hrvatski"},{"lang":"ht","name":"Haitian Creole","desc":"Haitian Creole"},{"lang":"hu","name":"Hungarian","desc":"Magyar"},{"lang":"id","name":"Indonesian","desc":"Indonesia"},{"lang":"is","name":"Icelandic","desc":"Íslenska"},{"lang":"it","name":"Italian","desc":"Italiano"},{"lang":"ja","name":"Japanese","desc":"日本語"},{"lang":"kn","name":"Kannada","desc":"ಕನ್ನಡ"},{"lang":"ko","name":"Korean","desc":"한국어"},{"lang":"lt","name":"Lithuanian","desc":"Lietuvių"},{"lang":"lv","name":"Latvian","desc":"Latviešu"},{"lang":"mg","name":"Malagasy","desc":"Malagasy"},{"lang":"mi","name":"Maori","desc":"Māori"},{"lang":"ml","name":"Malayalam","desc":"മലയാളം"},{"lang":"mr","name":"Marathi","desc":"मराठी"},{"lang":"ms","name":"Malay","desc":"Melayu"},{"lang":"mt","name":"Maltese","desc":"Il-Malti"},{"lang":"mww","name":"Hmong Daw","desc":"Hmong Daw"},{"lang":"nb","name":"Norwegian","desc":"Norsk"},{"lang":"nl","name":"Dutch","desc":"Nederlands"},{"lang":"otq","name":"Querétaro Otomi","desc":"Querétaro Otomi"},{"lang":"pa","name":"Punjabi","desc":"ਪੰਜਾਬੀ"},{"lang":"pl","name":"Polish","desc":"Polski"},{"lang":"pt","name":"Portuguese (Brazil)","desc":"Português (Brasil)"},{"lang":"pt-pt","name":"Portuguese (Portugal)","desc":"Português (Portugal)"},{"lang":"ro","name":"Romanian","desc":"Română"},{"lang":"ru","name":"Russian","desc":"Русский"},{"lang":"sk","name":"Slovak","desc":"Slovenčina"},{"lang":"sl","name":"Slovenian","desc":"Slovenščina"},{"lang":"sm","name":"Samoan","desc":"Samoan"},{"lang":"sr-Cyrl","name":"Serbian (Cyrillic)","desc":"srpski (ćirilica)"},{"lang":"sr-Latn","name":"Serbian (Latin)","desc":"srpski (latinica)"},{"lang":"sv","name":"Swedish","desc":"Svenska"},{"lang":"sw","name":"Swahili","desc":"Kiswahili"},{"lang":"ta","name":"Tamil","desc":"தமிழ்"},{"lang":"te","name":"Telugu","desc":"తెలుగు"},{"lang":"th","name":"Thai","desc":"ไทย"},{"lang":"tlh-Latn","name":"Klingon (Latin)","desc":"Klingon (Latin)"},{"lang":"tlh-Piqd","name":"Klingon (pIqaD)","desc":"Klingon (pIqaD)"},{"lang":"to","name":"Tongan","desc":"lea fakatonga"},{"lang":"tr","name":"Turkish","desc":"Türkçe"},{"lang":"ty","name":"Tahitian","desc":"Tahitian"},{"lang":"uk","name":"Ukrainian","desc":"Українська"},{"lang":"ur","name":"Urdu","desc":"اردو"},{"lang":"vi","name":"Vietnamese","desc":"Tiếng Việt"},{"lang":"yua","name":"Yucatec Maya","desc":"Yucatec Maya"},{"lang":"zh-Hans","name":"Chinese Simplified","desc":"简体中文"},{"lang":"zh-Hant","name":"Chinese Traditional","desc":"繁體中文"}] -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/plugins/tui.image-editor/tui-color-picker.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * TOAST UI Color Picker 3 | * @version 2.2.6 4 | * @author NHN FE Development Team 5 | * @license MIT 6 | */.tui-colorpicker-clearfix{zoom:1}.tui-colorpicker-clearfix:after{content:"";display:block;clear:both}.tui-colorpicker-vml{behavior:url(#default#VML);display:block}.tui-colorpicker-container,.tui-colorpicker-palette-container{width:152px}.tui-colorpicker-palette-container ul{width:152px;margin:0;padding:0}.tui-colorpicker-palette-container li{float:left;margin:0;padding:0 3px 3px 0;list-style:none}.tui-colorpicker-palette-button{display:block;overflow:hidden;outline:none;margin:0;padding:0;width:16px;height:16px;border:1px solid #ccc;cursor:pointer}.tui-colorpicker-palette-button.tui-colorpicker-selected{border:2px solid #000}.tui-colorpicker-palette-button.tui-colorpicker-color-transparent{barckground-repeat:repeat;background-repeat:no-repeat;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAOCAYAAAD0f5bSAAABfGlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGAqSSwoyGFhYGDIzSspCnJ3UoiIjFJgv8PAzcDDIMRgxSCemFxc4BgQ4MOAE3y7xsAIoi/rgsxK8/x506a1fP4WNq+ZclYlOrj1gQF3SmpxMgMDIweQnZxSnJwLZOcA2TrJBUUlQPYMIFu3vKQAxD4BZIsUAR0IZN8BsdMh7A8gdhKYzcQCVhMS5AxkSwDZAkkQtgaInQ5hW4DYyRmJKUC2B8guiBvAgNPDRcHcwFLXkYC7SQa5OaUwO0ChxZOaFxoMcgcQyzB4MLgwKDCYMxgwWDLoMjiWpFaUgBQ65xdUFmWmZ5QoOAJDNlXBOT+3oLQktUhHwTMvWU9HwcjA0ACkDhRnEKM/B4FNZxQ7jxDLX8jAYKnMwMDcgxBLmsbAsH0PA4PEKYSYyjwGBn5rBoZt5woSixLhDmf8xkKIX5xmbARh8zgxMLDe+///sxoDA/skBoa/E////73o//+/i4H2A+PsQA4AJHdp4IxrEg8AAAGbaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjEzPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjE0PC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CghrN1AAAABzSURBVCgVldKxEYAgDAXQD5VOpLuwgi4jlrTMqF00oOd5Aia/CcV/F4oYOgNlrLjvVyCEVJchBjEC25538PeaWTzRMBLxvIL7UZwFwL06qoA6aoAy+gFfJABvJAQPUoCMlICRRd8BzgHzJL4ok9aJ67l4AK9AxVKhHryUAAAAAElFTkSuQmCC")}.tui-colorpicker-palette-hex{font-family:monospace;width:60px}.tui-colorpicker-palette-hex,.tui-colorpicker-palette-preview{display:inline-block;*display:inline;zoom:1;vertical-align:middle}.tui-colorpicker-palette-preview{width:12px;height:12px;border:1px solid #ccc;overflow:hidden}.tui-colorpicker-palette-toggle-slider{display:inline-block;*display:inline;zoom:1;vertical-align:middle;float:right}.tui-colorpicker-slider-container{margin:5px 0 0;height:122px;zoom:1}.tui-colorpicker-slider-container:after{content:"";display:block;clear:both}.tui-colorpicker-slider-left{float:left;width:120px;height:120px}.tui-colorpicker-slider-right{float:right;width:32px;height:120px}.tui-colorpicker-svg{display:block}.tui-colorpicker-slider-handle{position:absolute;overflow:visible;top:0;left:0;width:1px;height:1px;z-index:2;opacity:.9}.tui-colorpicker-svg-slider,.tui-colorpicker-vml-slider{width:120px;height:120px;border:1px solid #ccc;overflow:hidden}.tui-colorpicker-vml-slider{position:relative}.tui-colorpicker-vml-slider-bg{position:absolute;margin:-1px 0 0 -1px;top:0;left:0;width:122px;height:122px}.tui-colorpicker-svg-huebar{float:right;width:18px;height:120px;border:1px solid #ccc;overflow:visible}.tui-colorpicker-vml-huebar{width:32px;position:relative}.tui-colorpicker-vml-huebar-bg{position:absolute;top:0;right:0;width:18px;height:121px} -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/UserDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | import lk.jiat.smarttrade.entity.Address; 4 | 5 | import java.io.Serializable; 6 | 7 | public class UserDTO implements Serializable { 8 | private int id; 9 | private String firstName; 10 | private String lastName; 11 | private String email; 12 | private String password; 13 | private String verificationCode; 14 | private String lineOne; 15 | private String lineTwo; 16 | private String postalCode; 17 | private boolean isPrimary; 18 | private int cityId; 19 | private String cityName; 20 | private String mobile; 21 | private String sinceAt; 22 | private String newPassword; 23 | private String confirmPassword; 24 | 25 | 26 | public UserDTO() { 27 | } 28 | 29 | public String getMobile() { 30 | return mobile; 31 | } 32 | 33 | public void setMobile(String mobile) { 34 | this.mobile = mobile; 35 | } 36 | 37 | public String getNewPassword() { 38 | return newPassword; 39 | } 40 | 41 | public void setNewPassword(String newPassword) { 42 | this.newPassword = newPassword; 43 | } 44 | 45 | public String getConfirmPassword() { 46 | return confirmPassword; 47 | } 48 | 49 | public void setConfirmPassword(String confirmPassword) { 50 | this.confirmPassword = confirmPassword; 51 | } 52 | 53 | public String getSinceAt() { 54 | return sinceAt; 55 | } 56 | 57 | public void setSinceAt(String sinceAt) { 58 | this.sinceAt = sinceAt; 59 | } 60 | 61 | public int getCityId() { 62 | return cityId; 63 | } 64 | 65 | public void setCityId(int cityId) { 66 | this.cityId = cityId; 67 | } 68 | 69 | public String getCityName() { 70 | return cityName; 71 | } 72 | 73 | public void setCityName(String cityName) { 74 | this.cityName = cityName; 75 | } 76 | 77 | public String getLineOne() { 78 | return lineOne; 79 | } 80 | 81 | public void setLineOne(String lineOne) { 82 | this.lineOne = lineOne; 83 | } 84 | 85 | public String getLineTwo() { 86 | return lineTwo; 87 | } 88 | 89 | public void setLineTwo(String lineTwo) { 90 | this.lineTwo = lineTwo; 91 | } 92 | 93 | public String getPostalCode() { 94 | return postalCode; 95 | } 96 | 97 | public void setPostalCode(String postalCode) { 98 | this.postalCode = postalCode; 99 | } 100 | 101 | public boolean isPrimary() { 102 | return isPrimary; 103 | } 104 | 105 | public void setPrimary(boolean primary) { 106 | isPrimary = primary; 107 | } 108 | 109 | public int getId() { 110 | return id; 111 | } 112 | 113 | public void setId(int id) { 114 | this.id = id; 115 | } 116 | 117 | public String getFirstName() { 118 | return firstName; 119 | } 120 | 121 | public void setFirstName(String firstName) { 122 | this.firstName = firstName; 123 | } 124 | 125 | public String getLastName() { 126 | return lastName; 127 | } 128 | 129 | public void setLastName(String lastName) { 130 | this.lastName = lastName; 131 | } 132 | 133 | public String getEmail() { 134 | return email; 135 | } 136 | 137 | public void setEmail(String email) { 138 | this.email = email; 139 | } 140 | 141 | public String getPassword() { 142 | return password; 143 | } 144 | 145 | public void setPassword(String password) { 146 | this.password = password; 147 | } 148 | 149 | public String getVerificationCode() { 150 | return verificationCode; 151 | } 152 | 153 | public void setVerificationCode(String verificationCode) { 154 | this.verificationCode = verificationCode; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.service; 2 | 3 | import lk.jiat.smarttrade.entity.*; 4 | import lk.jiat.smarttrade.util.HibernateUtil; 5 | import lk.jiat.smarttrade.validation.Validator; 6 | import org.hibernate.Session; 7 | import org.hibernate.Transaction; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | public class OrderService { 13 | public void completeOrder(String orderId) { 14 | int oid = Integer.parseInt(orderId.replaceAll(Validator.NON_DIGIT_PATTERN, "")); 15 | 16 | try (Session hibernateSession = HibernateUtil.getSessionFactory().openSession()) { 17 | Transaction transaction = hibernateSession.beginTransaction(); 18 | try { 19 | Order order = hibernateSession.find(Order.class, oid); 20 | if (order == null) { 21 | throw new RuntimeException("Order not found for ID: " + oid); 22 | } 23 | 24 | // Update stock quantities 25 | Set orderItems = order.getOrderItems(); 26 | if (orderItems != null) { 27 | for (OrderItem orderItem : orderItems) { 28 | Stock stock = orderItem.getStock(); 29 | if (stock != null) { 30 | int updatedQty = stock.getQty() - orderItem.getQty(); 31 | if (updatedQty < 0) { 32 | throw new RuntimeException("Insufficient stock for product: " 33 | + stock.getProduct().getTitle()); 34 | } 35 | stock.setQty(updatedQty); 36 | hibernateSession.merge(stock); 37 | } 38 | } 39 | } 40 | 41 | // Update order status 42 | Status completedStatus = hibernateSession.createNamedQuery("Status.findByValue", Status.class) 43 | .setParameter("value", String.valueOf(Status.Type.COMPLETED)) 44 | .getSingleResult(); 45 | order.setStatus(completedStatus); 46 | hibernateSession.merge(order); 47 | 48 | // Remove cart items 49 | List cartList = hibernateSession.createQuery("FROM Cart c WHERE c.user=:user", Cart.class) 50 | .setParameter("user", order.getUser()) 51 | .getResultList(); 52 | for (Cart cart : cartList) { 53 | hibernateSession.remove(cart); 54 | } 55 | 56 | transaction.commit(); 57 | } catch (Exception e) { 58 | transaction.rollback(); 59 | throw new RuntimeException("Failed to complete order: " + e.getMessage(), e); 60 | } 61 | } 62 | } 63 | 64 | public void failOrder(String orderId) { 65 | int oid = Integer.parseInt(orderId.replaceAll(Validator.NON_DIGIT_PATTERN, "")); 66 | 67 | try (Session hibernateSession = HibernateUtil.getSessionFactory().openSession()) { 68 | Transaction transaction = hibernateSession.beginTransaction(); 69 | try { 70 | Order order = hibernateSession.find(Order.class, oid); 71 | if (order == null) { 72 | throw new RuntimeException("Order not found for ID: " + oid); 73 | } 74 | 75 | Status rejectedStatus = hibernateSession.createNamedQuery("Status.findByValue", Status.class) 76 | .setParameter("value", String.valueOf(Status.Type.REJECTED)) 77 | .getSingleResult(); 78 | order.setStatus(rejectedStatus); 79 | hibernateSession.merge(order); 80 | 81 | transaction.commit(); 82 | } catch (Exception e) { 83 | transaction.rollback(); 84 | throw new RuntimeException("Failed to reject order: " + e.getMessage(), e); 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/ProductDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | public class ProductDTO implements Serializable { 7 | private int productId; 8 | private int brandId; 9 | private String brandName; 10 | private int modelId; 11 | private String modelName; 12 | private String title; 13 | private String description; 14 | private int storageId; 15 | private String storageValue; 16 | private int colorId; 17 | private String colorValue; 18 | private int qualityId; 19 | private String qualityValue; 20 | private double price; 21 | private int qty; 22 | private List stockDTOList; 23 | private List images; 24 | 25 | public List getImages() { 26 | return images; 27 | } 28 | 29 | public void setImages(List images) { 30 | this.images = images; 31 | } 32 | 33 | public List getStockDTOList() { 34 | return stockDTOList; 35 | } 36 | 37 | public void setStockDTOList(List stockDTOList) { 38 | this.stockDTOList = stockDTOList; 39 | } 40 | 41 | public int getProductId() { 42 | return productId; 43 | } 44 | 45 | public void setProductId(int productId) { 46 | this.productId = productId; 47 | } 48 | 49 | public int getBrandId() { 50 | return brandId; 51 | } 52 | 53 | public void setBrandId(int brandId) { 54 | this.brandId = brandId; 55 | } 56 | 57 | public String getBrandName() { 58 | return brandName; 59 | } 60 | 61 | public void setBrandName(String brandName) { 62 | this.brandName = brandName; 63 | } 64 | 65 | public int getModelId() { 66 | return modelId; 67 | } 68 | 69 | public void setModelId(int modelId) { 70 | this.modelId = modelId; 71 | } 72 | 73 | public String getModelName() { 74 | return modelName; 75 | } 76 | 77 | public void setModelName(String modelName) { 78 | this.modelName = modelName; 79 | } 80 | 81 | public String getTitle() { 82 | return title; 83 | } 84 | 85 | public void setTitle(String title) { 86 | this.title = title; 87 | } 88 | 89 | public String getDescription() { 90 | return description; 91 | } 92 | 93 | public void setDescription(String description) { 94 | this.description = description; 95 | } 96 | 97 | public int getStorageId() { 98 | return storageId; 99 | } 100 | 101 | public void setStorageId(int storageId) { 102 | this.storageId = storageId; 103 | } 104 | 105 | public String getStorageValue() { 106 | return storageValue; 107 | } 108 | 109 | public void setStorageValue(String storageValue) { 110 | this.storageValue = storageValue; 111 | } 112 | 113 | public int getColorId() { 114 | return colorId; 115 | } 116 | 117 | public void setColorId(int colorId) { 118 | this.colorId = colorId; 119 | } 120 | 121 | public String getColorValue() { 122 | return colorValue; 123 | } 124 | 125 | public void setColorValue(String colorValue) { 126 | this.colorValue = colorValue; 127 | } 128 | 129 | public int getQualityId() { 130 | return qualityId; 131 | } 132 | 133 | public void setQualityId(int qualityId) { 134 | this.qualityId = qualityId; 135 | } 136 | 137 | public String getQualityValue() { 138 | return qualityValue; 139 | } 140 | 141 | public void setQualityValue(String qualityValue) { 142 | this.qualityValue = qualityValue; 143 | } 144 | 145 | public double getPrice() { 146 | return price; 147 | } 148 | 149 | public void setPrice(double price) { 150 | this.price = price; 151 | } 152 | 153 | public int getQty() { 154 | return qty; 155 | } 156 | 157 | public void setQty(int qty) { 158 | this.qty = qty; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/webapp/assets/css/vendor/slick-theme.css: -------------------------------------------------------------------------------- 1 | /* Slider */ 2 | .slick-loading .slick-list { 3 | background: #fff url('../../images/ajax-loader.gif') center center no-repeat; 4 | } 5 | 6 | /* Icons */ 7 | @font-face { 8 | font-family: 'slick'; 9 | font-weight: normal; 10 | font-style: normal; 11 | src: url('../../fonts/slick.eot'); 12 | src: url('../../fonts/slick.eot?#iefix') format('embedded-opentype'), url('../../fonts/slick.woff') format('woff'), url('../../fonts/slick.ttf') format('truetype'), url('../../fonts/slick.svg#slick') format('svg'); 13 | } 14 | 15 | 16 | /* Arrows */ 17 | .slick-prev, 18 | .slick-next { 19 | font-size: 0; 20 | line-height: 0; 21 | position: absolute; 22 | top: 50%; 23 | display: block; 24 | width: 20px; 25 | height: 20px; 26 | padding: 0; 27 | -webkit-transform: translate(0, -50%); 28 | -ms-transform: translate(0, -50%); 29 | transform: translate(0, -50%); 30 | cursor: pointer; 31 | color: transparent; 32 | border: none; 33 | outline: none; 34 | background: transparent; 35 | } 36 | 37 | .slick-prev:hover, 38 | .slick-prev:focus, 39 | .slick-next:hover, 40 | .slick-next:focus { 41 | color: transparent; 42 | outline: none; 43 | background: transparent; 44 | } 45 | 46 | .slick-prev:hover:before, 47 | .slick-prev:focus:before, 48 | .slick-next:hover:before, 49 | .slick-next:focus:before { 50 | opacity: 1; 51 | } 52 | 53 | .slick-prev.slick-disabled:before, 54 | .slick-next.slick-disabled:before { 55 | opacity: .25; 56 | } 57 | 58 | .slick-prev:before, 59 | .slick-next:before { 60 | font-family: 'slick'; 61 | font-size: 20px; 62 | line-height: 1; 63 | opacity: .75; 64 | color: white; 65 | -webkit-font-smoothing: antialiased; 66 | -moz-osx-font-smoothing: grayscale; 67 | } 68 | 69 | .slick-prev { 70 | left: -25px; 71 | } 72 | 73 | [dir='rtl'] .slick-prev { 74 | right: -25px; 75 | left: auto; 76 | } 77 | 78 | .slick-prev:before { 79 | content: '←'; 80 | } 81 | 82 | [dir='rtl'] .slick-prev:before { 83 | content: '→'; 84 | } 85 | 86 | .slick-next { 87 | right: -25px; 88 | } 89 | 90 | [dir='rtl'] .slick-next { 91 | right: auto; 92 | left: -25px; 93 | } 94 | 95 | .slick-next:before { 96 | content: '→'; 97 | } 98 | 99 | [dir='rtl'] .slick-next:before { 100 | content: '←'; 101 | } 102 | 103 | /* Dots */ 104 | .slick-dotted.slick-slider { 105 | margin-bottom: 30px; 106 | } 107 | 108 | .slick-dots { 109 | position: absolute; 110 | bottom: -25px; 111 | 112 | display: block; 113 | 114 | width: 100%; 115 | padding: 0; 116 | margin: 0; 117 | 118 | list-style: none; 119 | 120 | text-align: center; 121 | } 122 | 123 | .slick-dots li { 124 | position: relative; 125 | 126 | display: inline-block; 127 | 128 | width: 20px; 129 | height: 20px; 130 | margin: 0 5px; 131 | padding: 0; 132 | 133 | cursor: pointer; 134 | } 135 | 136 | .slick-dots li button { 137 | font-size: 0; 138 | line-height: 0; 139 | 140 | display: block; 141 | 142 | width: 20px; 143 | height: 20px; 144 | padding: 5px; 145 | 146 | cursor: pointer; 147 | 148 | color: transparent; 149 | border: 0; 150 | outline: none; 151 | background: transparent; 152 | } 153 | 154 | .slick-dots li button:hover, 155 | .slick-dots li button:focus { 156 | outline: none; 157 | } 158 | 159 | .slick-dots li button:hover:before, 160 | .slick-dots li button:focus:before { 161 | opacity: 1; 162 | } 163 | 164 | .slick-dots li button:before { 165 | font-family: 'slick'; 166 | font-size: 6px; 167 | line-height: 20px; 168 | 169 | position: absolute; 170 | top: 0; 171 | left: 0; 172 | 173 | width: 20px; 174 | height: 20px; 175 | 176 | content: '•'; 177 | text-align: center; 178 | 179 | opacity: .25; 180 | color: black; 181 | 182 | -webkit-font-smoothing: antialiased; 183 | -moz-osx-font-smoothing: grayscale; 184 | } 185 | 186 | .slick-dots li.slick-active button:before { 187 | opacity: .75; 188 | color: black; 189 | } -------------------------------------------------------------------------------- /src/main/webapp/assets/js/vendor/js.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * JavaScript Cookie v2.1.3 3 | * https://github.com/js-cookie/js-cookie 4 | * 5 | * Copyright 2006, 2015 Klaus Hartl & Fagner Brack 6 | * Released under the MIT license 7 | */ 8 | ;(function (factory) { 9 | var registeredInModuleLoader = false; 10 | if (typeof define === 'function' && define.amd) { 11 | define(factory); 12 | registeredInModuleLoader = true; 13 | } 14 | if (typeof exports === 'object') { 15 | module.exports = factory(); 16 | registeredInModuleLoader = true; 17 | } 18 | if (!registeredInModuleLoader) { 19 | var OldCookies = window.Cookies; 20 | var api = window.Cookies = factory(); 21 | api.noConflict = function () { 22 | window.Cookies = OldCookies; 23 | return api; 24 | }; 25 | } 26 | }(function () { 27 | function extend () { 28 | var i = 0; 29 | var result = {}; 30 | for (; i < arguments.length; i++) { 31 | var attributes = arguments[ i ]; 32 | for (var key in attributes) { 33 | result[key] = attributes[key]; 34 | } 35 | } 36 | return result; 37 | } 38 | 39 | function init (converter) { 40 | function api (key, value, attributes) { 41 | var result; 42 | if (typeof document === 'undefined') { 43 | return; 44 | } 45 | 46 | // Write 47 | 48 | if (arguments.length > 1) { 49 | attributes = extend({ 50 | path: '/' 51 | }, api.defaults, attributes); 52 | 53 | if (typeof attributes.expires === 'number') { 54 | var expires = new Date(); 55 | expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); 56 | attributes.expires = expires; 57 | } 58 | 59 | try { 60 | result = JSON.stringify(value); 61 | if (/^[\{\[]/.test(result)) { 62 | value = result; 63 | } 64 | } catch (e) {} 65 | 66 | if (!converter.write) { 67 | value = encodeURIComponent(String(value)) 68 | .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); 69 | } else { 70 | value = converter.write(value, key); 71 | } 72 | 73 | key = encodeURIComponent(String(key)); 74 | key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); 75 | key = key.replace(/[\(\)]/g, escape); 76 | 77 | return (document.cookie = [ 78 | key, '=', value, 79 | attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 80 | attributes.path ? '; path=' + attributes.path : '', 81 | attributes.domain ? '; domain=' + attributes.domain : '', 82 | attributes.secure ? '; secure' : '' 83 | ].join('')); 84 | } 85 | 86 | // Read 87 | 88 | if (!key) { 89 | result = {}; 90 | } 91 | 92 | // To prevent the for loop in the first place assign an empty array 93 | // in case there are no cookies at all. Also prevents odd result when 94 | // calling "get()" 95 | var cookies = document.cookie ? document.cookie.split('; ') : []; 96 | var rdecode = /(%[0-9A-Z]{2})+/g; 97 | var i = 0; 98 | 99 | for (; i < cookies.length; i++) { 100 | var parts = cookies[i].split('='); 101 | var cookie = parts.slice(1).join('='); 102 | 103 | if (cookie.charAt(0) === '"') { 104 | cookie = cookie.slice(1, -1); 105 | } 106 | 107 | try { 108 | var name = parts[0].replace(rdecode, decodeURIComponent); 109 | cookie = converter.read ? 110 | converter.read(cookie, name) : converter(cookie, name) || 111 | cookie.replace(rdecode, decodeURIComponent); 112 | 113 | if (this.json) { 114 | try { 115 | cookie = JSON.parse(cookie); 116 | } catch (e) {} 117 | } 118 | 119 | if (key === name) { 120 | result = cookie; 121 | break; 122 | } 123 | 124 | if (!key) { 125 | result[name] = cookie; 126 | } 127 | } catch (e) {} 128 | } 129 | 130 | return result; 131 | } 132 | 133 | api.set = api; 134 | api.get = function (key) { 135 | return api.call(api, key); 136 | }; 137 | api.getJSON = function () { 138 | return api.apply({ 139 | json: true 140 | }, [].slice.call(arguments)); 141 | }; 142 | api.defaults = {}; 143 | 144 | api.remove = function (key, attributes) { 145 | api(key, '', extend(attributes, { 146 | expires: -1 147 | })); 148 | }; 149 | 150 | api.withConverter = init; 151 | 152 | return api; 153 | } 154 | 155 | return init(function () {}); 156 | })); 157 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/controller/api/ProductController.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.controller.api; 2 | 3 | import com.google.gson.JsonObject; 4 | import jakarta.servlet.ServletContext; 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import jakarta.ws.rs.*; 7 | import jakarta.ws.rs.core.Context; 8 | import jakarta.ws.rs.core.MediaType; 9 | import jakarta.ws.rs.core.Response; 10 | import lk.jiat.smarttrade.dto.ProductDTO; 11 | import lk.jiat.smarttrade.entity.Product; 12 | import lk.jiat.smarttrade.service.FileUploadService; 13 | import lk.jiat.smarttrade.service.ProductService; 14 | import lk.jiat.smarttrade.util.AppUtil; 15 | import org.glassfish.jersey.media.multipart.ContentDisposition; 16 | import org.glassfish.jersey.media.multipart.FormDataBodyPart; 17 | import org.glassfish.jersey.media.multipart.FormDataParam; 18 | 19 | import java.io.InputStream; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | 24 | @Path("/products") 25 | public class ProductController { 26 | @Path("/advanced-search") 27 | @POST 28 | @Consumes(MediaType.APPLICATION_JSON) 29 | @Produces(MediaType.APPLICATION_JSON) 30 | public Response loadAdvancedSearchData(String requestData) { 31 | JsonObject requestObject = AppUtil.GSON.fromJson(requestData, JsonObject.class); 32 | String responseJson = new ProductService().loadAdvancedSearchData(requestObject); 33 | return Response.ok().entity(responseJson).build(); 34 | } 35 | 36 | @Path("/similar-products") 37 | @GET 38 | @Produces(MediaType.APPLICATION_JSON) 39 | public Response loadSimilarProducts(@QueryParam("productId") int id) { 40 | String responseJson = new ProductService().getSimilarProducts(id); 41 | return Response.ok().entity(responseJson).build(); 42 | } 43 | 44 | @Path("/single-product") 45 | @GET 46 | @Produces(MediaType.APPLICATION_JSON) 47 | // Fetch product id from request 48 | // .../single-product?productId=1 49 | public Response loadSingleProduct(@QueryParam("productId") int id) { 50 | String responseJson = new ProductService().getSingleProduct(id); 51 | return Response.ok().entity(responseJson).build(); 52 | } 53 | 54 | 55 | @Path("/all") 56 | @GET 57 | @Produces(MediaType.APPLICATION_JSON) 58 | public Response loadAllUserProducts(@Context HttpServletRequest request) { 59 | String responseJson = new ProductService().getAllUserProducts(request); 60 | return Response.ok().entity(responseJson).build(); 61 | } 62 | 63 | @Path("/{productId}/upload-images") 64 | @PUT 65 | @Consumes(MediaType.MULTIPART_FORM_DATA) 66 | @Produces(MediaType.APPLICATION_JSON) 67 | public Response uploadProductImages( 68 | @PathParam("productId") int productId, 69 | @FormDataParam("images[]") FormDataBodyPart formDataBodyPart, 70 | @Context ServletContext context) { 71 | List fileItems = new ArrayList<>(); 72 | FileUploadService fileUploadService = new FileUploadService(context); 73 | ProductService productService = new ProductService(); 74 | Product product = productService.getProductById(productId); 75 | 76 | formDataBodyPart.getParent().getBodyParts().forEach(bodyPart -> { 77 | InputStream inputStream = bodyPart.getEntityAs(InputStream.class); 78 | ContentDisposition contentDisposition = bodyPart.getContentDisposition(); 79 | System.out.println(contentDisposition.getFileName()); 80 | FileUploadService.FileItem fileItem = fileUploadService.uploadFile("product/" + productId, inputStream, contentDisposition); 81 | fileItems.add(fileItem); 82 | product.getImages().add(fileItem.getFullUrl()); 83 | }); 84 | String responseJson = productService.updateProduct(product); 85 | return Response.ok().entity(responseJson).build(); 86 | } 87 | 88 | @Path("/save-product") 89 | @POST 90 | @Consumes(MediaType.MULTIPART_FORM_DATA) 91 | @Produces(MediaType.APPLICATION_JSON) 92 | public Response saveProduct(@FormDataParam("product") String productJson, @Context HttpServletRequest request) { 93 | ProductDTO productDTO = AppUtil.GSON.fromJson(productJson, ProductDTO.class); 94 | String responseJson = new ProductService().addNewProduct(productDTO, request); 95 | return Response.ok().entity(responseJson).build(); 96 | } 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/service/FileUploadService.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.service; 2 | 3 | import jakarta.servlet.ServletContext; 4 | import jakarta.ws.rs.WebApplicationException; 5 | import lk.jiat.smarttrade.util.Env; 6 | import org.apache.commons.io.FilenameUtils; 7 | import org.glassfish.jersey.media.multipart.ContentDisposition; 8 | 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | import java.nio.file.Files; 14 | import java.nio.file.Path; 15 | import java.nio.file.Paths; 16 | 17 | public class FileUploadService { 18 | private static final String UPLOAD_DIRECTORY_NAME = "/uploads"; 19 | private final ServletContext context; 20 | 21 | public FileUploadService(ServletContext context) { 22 | this.context = context; 23 | } 24 | 25 | public FileItem uploadFile(String directoryName, InputStream inputStream, ContentDisposition fileMetaData) { 26 | return writeFile(UPLOAD_DIRECTORY_NAME + "/" + directoryName, inputStream, fileMetaData); 27 | } 28 | 29 | private FileItem writeFile(String pathName, InputStream inputStream, ContentDisposition contentDisposition) { 30 | Path uploadPath = Paths.get(context.getRealPath(pathName)); 31 | String extension = FilenameUtils.getExtension(contentDisposition.getFileName()); 32 | String fileName = System.currentTimeMillis() + "." + extension; 33 | 34 | if (!Files.exists(uploadPath)) { 35 | try { 36 | System.out.println("Upload path not found. Creating Directory: \"" + uploadPath + "\""); 37 | Files.createDirectories(uploadPath); 38 | } catch (IOException e) { 39 | throw new RuntimeException(e); 40 | } 41 | } 42 | 43 | try { 44 | int read; 45 | byte[] bytes = new byte[1024]; 46 | OutputStream outputStream = new FileOutputStream(uploadPath + "/" + fileName); 47 | while ((read = inputStream.read(bytes)) != -1) { 48 | outputStream.write(bytes, 0, read); 49 | } 50 | outputStream.flush(); 51 | outputStream.close(); 52 | } catch (IOException e) { 53 | throw new WebApplicationException("Error while file uploading! Try Again..."); 54 | } 55 | 56 | String appUrl = Env.get("app.url"); 57 | /* 58 | * http://localhost:8080/smarttrade/UPLOAD_DIRECTORY_NAME/subDirecotry/productId/fileName 59 | * http://localhost:8080/smarttrade/uploads/product/1/123456.png 60 | * */ 61 | String url = context.getContextPath() + uploadPath + "/" + fileName; 62 | String path = uploadPath + "/" + fileName; 63 | String fullUrl = appUrl + "/" + uploadPath + "/" + fileName; 64 | 65 | return new FileItem(fileName, contentDisposition.getFileName(), path, url, fullUrl); 66 | } 67 | 68 | public static class FileItem { 69 | private String fileName; 70 | private String originalFileName; 71 | private String filePath; 72 | private String url; 73 | private String fullUrl; 74 | 75 | public FileItem(String fileName, String originalFileName, String filePath, String url, String fullUrl) { 76 | this.fileName = fileName; 77 | this.originalFileName = originalFileName; 78 | this.filePath = filePath; 79 | this.url = url; 80 | this.fullUrl = fullUrl; 81 | } 82 | 83 | public void setFileName(String fileName) { 84 | this.fileName = fileName; 85 | } 86 | 87 | public void setOriginalFileName(String originalFileName) { 88 | this.originalFileName = originalFileName; 89 | } 90 | 91 | public void setFilePath(String filePath) { 92 | this.filePath = filePath; 93 | } 94 | 95 | public void setUrl(String url) { 96 | this.url = url; 97 | } 98 | 99 | public void setFullUrl(String fullUrl) { 100 | this.fullUrl = fullUrl; 101 | } 102 | 103 | public String getFileName() { 104 | return fileName; 105 | } 106 | 107 | public String getOriginalFileName() { 108 | return originalFileName; 109 | } 110 | 111 | public String getFilePath() { 112 | return filePath; 113 | } 114 | 115 | public String getUrl() { 116 | return url; 117 | } 118 | 119 | public String getFullUrl() { 120 | return fullUrl; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | lk.jiat 8 | SmartTrade 9 | 1.0 10 | war 11 | smarttrade 12 | 13 | 14 | 15 | org.apache.tomcat.embed 16 | tomcat-embed-core 17 | 10.1.7 18 | 19 | 20 | org.apache.tomcat.embed 21 | tomcat-embed-jasper 22 | 10.1.7 23 | 24 | 25 | jakarta.servlet 26 | jakarta.servlet-api 27 | 6.1.0 28 | provided 29 | 30 | 31 | org.hibernate.orm 32 | hibernate-core 33 | 6.1.7.Final 34 | 35 | 36 | 37 | org.hibernate.validator 38 | hibernate-validator 39 | 8.0.0.Final 40 | 41 | 42 | 43 | com.mysql 44 | mysql-connector-j 45 | 9.0.0 46 | 47 | 48 | 49 | 50 | 51 | org.glassfish.jersey.containers 52 | jersey-container-servlet-core 53 | 3.1.2 54 | 55 | 56 | 57 | org.glassfish.jersey.inject 58 | jersey-hk2 59 | 3.1.2 60 | 61 | 62 | org.glassfish.jersey.media 63 | jersey-media-multipart 64 | 3.1.2 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.angus 71 | jakarta.mail 72 | 2.0.2 73 | 74 | 75 | com.sun.mail 76 | jakarta.mail 77 | 2.0.1 78 | 79 | 80 | jakarta.activation 81 | jakarta.activation-api 82 | 2.1.2 83 | 84 | 85 | 86 | 87 | 88 | io.rocketbase.mail 89 | email-template-builder 90 | 2.4.0 91 | 92 | 93 | 94 | 95 | com.google.code.gson 96 | gson 97 | 2.10.1 98 | 99 | 100 | 101 | 102 | commons-io 103 | commons-io 104 | 2.16.1 105 | 106 | 107 | 108 | 109 | 110 | ${name} 111 | 112 | 113 | org.apache.maven.plugins 114 | maven-war-plugin 115 | 3.4.0 116 | 117 | 118 | 119 | 120 | 17 121 | 17 122 | UTF-8 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/main/java/lk/jiat/smarttrade/dto/PayHereDTO.java: -------------------------------------------------------------------------------- 1 | package lk.jiat.smarttrade.dto; 2 | 3 | public class PayHereDTO { 4 | /* make dto for the required PayHere parameters 5 | Required Parameters 6 | merchant_id - PayHere Merchant ID 7 | return_url - URL to redirect users when success 8 | cancel_url - URL to redirect users when cancelled 9 | notify_url - URL to call back the status of the payment (Needs to be a URL accessible on a public IP/domain) 10 | first_name - Customer’s First Name 11 | last_name - Customer’s Last Name 12 | email - Customer’s Email 13 | phone - Customer’s Phone No 14 | address - Customer’s Address Line1 + Line2 15 | city - Customer’s City 16 | country - Customer’s Country 17 | order_id - Order ID generated by the merchant 18 | items - Item title or Order/Invoice number 19 | currency - Currency Code (LKR/USD) 20 | amount - Total Payment Amount 21 | hash - Generated hash value as mentioned below (*Required from 2023-01-16) 22 | */ 23 | private boolean sandbox; 24 | private String merchant_id; 25 | private String return_url; 26 | private String cancel_url; 27 | private String notify_url; 28 | private String first_name; 29 | private String last_name; 30 | private String email; 31 | private String phone; 32 | private String address; 33 | private String city; 34 | private String country; 35 | private String order_id; 36 | private String items; 37 | private String currency; 38 | private String amount; 39 | private String hash; 40 | 41 | public boolean isSandbox() { 42 | return sandbox; 43 | } 44 | 45 | public void setSandbox(boolean sandbox) { 46 | this.sandbox = sandbox; 47 | } 48 | 49 | public String getMerchantId() { 50 | return merchant_id; 51 | } 52 | 53 | public void setMerchantId(String merchant_id) { 54 | this.merchant_id = merchant_id; 55 | } 56 | 57 | public String getReturnURL() { 58 | return return_url; 59 | } 60 | 61 | public void setReturnURL(String return_url) { 62 | this.return_url = return_url; 63 | } 64 | 65 | public String getCancelURL() { 66 | return cancel_url; 67 | } 68 | 69 | public void setCancelURL(String cancel_url) { 70 | this.cancel_url = cancel_url; 71 | } 72 | 73 | public String getNotifyURL() { 74 | return notify_url; 75 | } 76 | 77 | public void setNotifyURL(String notify_url) { 78 | this.notify_url = notify_url; 79 | } 80 | 81 | public String getFirstName() { 82 | return first_name; 83 | } 84 | 85 | public void setFirstName(String first_name) { 86 | this.first_name = first_name; 87 | } 88 | 89 | public String getLastName() { 90 | return last_name; 91 | } 92 | 93 | public void setLastName(String last_name) { 94 | this.last_name = last_name; 95 | } 96 | 97 | public String getEmail() { 98 | return email; 99 | } 100 | 101 | public void setEmail(String email) { 102 | this.email = email; 103 | } 104 | 105 | public String getPhone() { 106 | return phone; 107 | } 108 | 109 | public void setPhone(String phone) { 110 | this.phone = phone; 111 | } 112 | 113 | public String getAddress() { 114 | return address; 115 | } 116 | 117 | public void setAddress(String address) { 118 | this.address = address; 119 | } 120 | 121 | public String getCity() { 122 | return city; 123 | } 124 | 125 | public void setCity(String city) { 126 | this.city = city; 127 | } 128 | 129 | public String getCountry() { 130 | return country; 131 | } 132 | 133 | public void setCountry(String country) { 134 | this.country = country; 135 | } 136 | 137 | public String getOrderId() { 138 | return order_id; 139 | } 140 | 141 | public void setOrderId(String orderId) { 142 | this.order_id = orderId; 143 | } 144 | 145 | public String getItems() { 146 | return items; 147 | } 148 | 149 | public void setItems(String items) { 150 | this.items = items; 151 | } 152 | 153 | public String getCurrency() { 154 | return currency; 155 | } 156 | 157 | public void setCurrency(String currency) { 158 | this.currency = currency; 159 | } 160 | 161 | public String getAmount() { 162 | return amount; 163 | } 164 | 165 | public void setAmount(String amount) { 166 | this.amount = amount; 167 | } 168 | 169 | public String getHash() { 170 | return hash; 171 | } 172 | 173 | public void setHash(String hash) { 174 | this.hash = hash; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/main/webapp/assets/css/vendor/flaticon/flaticon.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "flaticon"; 3 | src: url("./flaticon.ttf?407e24229cdad6f8c9e45e028e090cfd") format("truetype"), 4 | url("./flaticon.woff?407e24229cdad6f8c9e45e028e090cfd") format("woff"), 5 | url("./flaticon.woff2?407e24229cdad6f8c9e45e028e090cfd") format("woff2"), 6 | url("./flaticon.eot?407e24229cdad6f8c9e45e028e090cfd#iefix") format("embedded-opentype"), 7 | url("./flaticon.svg?407e24229cdad6f8c9e45e028e090cfd#flaticon") format("svg"); 8 | } 9 | 10 | i[class^="flaticon-"]:before, i[class*=" flaticon-"]:before { 11 | font-family: flaticon !important; 12 | font-style: normal; 13 | font-weight: normal !important; 14 | font-variant: normal; 15 | text-transform: none; 16 | line-height: 1; 17 | -webkit-font-smoothing: antialiased; 18 | -moz-osx-font-smoothing: grayscale; 19 | } 20 | 21 | .flaticon-arrow-down:before { 22 | content: "\f101"; 23 | } 24 | .flaticon-shopping-cart:before { 25 | content: "\f102"; 26 | } 27 | .flaticon-person:before { 28 | content: "\f103"; 29 | } 30 | .flaticon-magnifying-glass:before { 31 | content: "\f104"; 32 | } 33 | .flaticon-right-arrow:before { 34 | content: "\f105"; 35 | } 36 | .flaticon-close:before { 37 | content: "\f106"; 38 | } 39 | .flaticon-left-arrow:before { 40 | content: "\f107"; 41 | } 42 | .flaticon-exchange:before { 43 | content: "\f108"; 44 | } 45 | .flaticon-visibility:before { 46 | content: "\f109"; 47 | } 48 | .flaticon-heart:before { 49 | content: "\f10a"; 50 | } 51 | .flaticon-box:before { 52 | content: "\f10b"; 53 | } 54 | .flaticon-truck:before { 55 | content: "\f10c"; 56 | } 57 | .flaticon-credit-card:before { 58 | content: "\f10d"; 59 | } 60 | .flaticon-24-hours:before { 61 | content: "\f10e"; 62 | } 63 | .flaticon-headphones:before { 64 | content: "\f10f"; 65 | } 66 | .flaticon-cashback:before { 67 | content: "\f110"; 68 | } 69 | .flaticon-facebook:before { 70 | content: "\f111"; 71 | } 72 | .flaticon-twitter:before { 73 | content: "\f112"; 74 | } 75 | .flaticon-spotify:before { 76 | content: "\f113"; 77 | } 78 | .flaticon-youtube:before { 79 | content: "\f114"; 80 | } 81 | .flaticon-odnoklassniki:before { 82 | content: "\f115"; 83 | } 84 | .flaticon-behance:before { 85 | content: "\f116"; 86 | } 87 | .flaticon-linkedin:before { 88 | content: "\f117"; 89 | } 90 | .flaticon-star:before { 91 | content: "\f118"; 92 | } 93 | .flaticon-star-1:before { 94 | content: "\f119"; 95 | } 96 | .flaticon-menu:before { 97 | content: "\f11a"; 98 | } 99 | .flaticon-menu-bar:before { 100 | content: "\f11b"; 101 | } 102 | .flaticon-plus:before { 103 | content: "\f11c"; 104 | } 105 | .flaticon-envelope:before { 106 | content: "\f11d"; 107 | } 108 | .flaticon-envelope-1:before { 109 | content: "\f11e"; 110 | } 111 | .flaticon-points:before { 112 | content: "\f11f"; 113 | } 114 | .flaticon-ellipsis:before { 115 | content: "\f120"; 116 | } 117 | .flaticon-tag:before { 118 | content: "\f121"; 119 | } 120 | .flaticon-minus:before { 121 | content: "\f122"; 122 | } 123 | .flaticon-van:before { 124 | content: "\f123"; 125 | } 126 | .flaticon-award:before { 127 | content: "\f124"; 128 | } 129 | .flaticon-quality:before { 130 | content: "\f125"; 131 | } 132 | .flaticon-virus:before { 133 | content: "\f126"; 134 | } 135 | .flaticon-product-return:before { 136 | content: "\f127"; 137 | } 138 | .flaticon-expand:before { 139 | content: "\f128"; 140 | } 141 | .flaticon-shop:before { 142 | content: "\f129"; 143 | } 144 | .flaticon-menu-1:before { 145 | content: "\f12a"; 146 | } 147 | .flaticon-more:before { 148 | content: "\f12b"; 149 | } 150 | .flaticon-list:before { 151 | content: "\f12c"; 152 | } 153 | .flaticon-menu-2:before { 154 | content: "\f12d"; 155 | } 156 | .flaticon-map:before { 157 | content: "\f12e"; 158 | } 159 | .flaticon-lock:before { 160 | content: "\f12f"; 161 | } 162 | .flaticon-key:before { 163 | content: "\f130"; 164 | } 165 | .flaticon-suitcase:before { 166 | content: "\f131"; 167 | } 168 | .flaticon-id-card:before { 169 | content: "\f132"; 170 | } 171 | .flaticon-tick:before { 172 | content: "\f133"; 173 | } 174 | .flaticon-call:before { 175 | content: "\f134"; 176 | } 177 | .flaticon-time:before { 178 | content: "\f135"; 179 | } 180 | .flaticon-location-marker:before { 181 | content: "\f136"; 182 | } 183 | .flaticon-earphones:before { 184 | content: "\f137"; 185 | } 186 | .flaticon-warning-sign:before { 187 | content: "\f138"; 188 | } 189 | .flaticon-calendar:before { 190 | content: "\f139"; 191 | } 192 | .flaticon-calendar-1:before { 193 | content: "\f13a"; 194 | } 195 | .flaticon-quote:before { 196 | content: "\f13b"; 197 | } 198 | .flaticon-chat:before { 199 | content: "\f13c"; 200 | } 201 | .flaticon-reply:before { 202 | content: "\f13d"; 203 | } 204 | -------------------------------------------------------------------------------- /src/main/webapp/verify-account.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Smart Trade 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 84 | 85 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /src/main/webapp/assets/js/vendor/jquery.countdown.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/) 3 | * Copyright (c) 2016 Edson Hilios 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * 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, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | !function(a){"use strict";"function"==typeof define&&define.amd?define(["src/main/webapp/assets/js/vendor/jquery"],a):a(jQuery)}(function(a){"use strict";function b(a){if(a instanceof Date)return a;if(String(a).match(g))return String(a).match(/^[0-9]*$/)&&(a=Number(a)),String(a).match(/\-/)&&(a=String(a).replace(/\-/g,"/")),new Date(a);throw new Error("Couldn't cast `"+a+"` to a date object.")}function c(a){var b=a.toString().replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1");return new RegExp(b)}function d(a){return function(b){var d=b.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);if(d)for(var f=0,g=d.length; f1?c:d}var f=[],g=[],h={precision:100,elapse:!1,defer:!1};g.push(/^[0-9]*$/.source),g.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),g.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),g=new RegExp(g.join("|"));var i={Y:"years",m:"months",n:"daysToMonth",d:"daysToWeek",w:"weeks",W:"weeksToMonth",H:"hours",M:"minutes",S:"seconds",D:"totalDays",I:"totalHours",N:"totalMinutes",T:"totalSeconds"},j=function(b, c, d){this.el=b,this.$el=a(b),this.interval=null,this.offset={},this.options=a.extend({},h),this.instanceNumber=f.length,f.push(this),this.$el.data("countdown-instance",this.instanceNumber),d&&("function"==typeof d?(this.$el.on("update.countdown",d),this.$el.on("stoped.countdown",d),this.$el.on("finish.countdown",d)):this.options=a.extend({},h,d)),this.setFinalDate(c),this.options.defer===!1&&this.start()};a.extend(j.prototype,{start:function(){null!==this.interval&&clearInterval(this.interval);var a=this;this.update(),this.interval=setInterval(function(){a.update.call(a)},this.options.precision)},stop:function(){clearInterval(this.interval),this.interval=null,this.dispatchEvent("stoped")},toggle:function(){this.interval?this.stop():this.start()},pause:function(){this.stop()},resume:function(){this.start()},remove:function(){this.stop.call(this),f[this.instanceNumber]=null,delete this.$el.data().countdownInstance},setFinalDate:function(a){this.finalDate=b(a)},update:function(){if(0===this.$el.closest("html").length)return void this.remove();var b,c=void 0!==a._data(this.el,"events"),d=new Date;b=this.finalDate.getTime()-d.getTime(),b=Math.ceil(b/1e3),b=!this.options.elapse&&b<0?0:Math.abs(b),this.totalSecsLeft!==b&&c&&(this.totalSecsLeft=b,this.elapsed=d>=this.finalDate,this.offset={seconds:this.totalSecsLeft%60,minutes:Math.floor(this.totalSecsLeft/60)%60,hours:Math.floor(this.totalSecsLeft/60/60)%24,days:Math.floor(this.totalSecsLeft/60/60/24)%7,daysToWeek:Math.floor(this.totalSecsLeft/60/60/24)%7,daysToMonth:Math.floor(this.totalSecsLeft/60/60/24%30.4368),weeks:Math.floor(this.totalSecsLeft/60/60/24/7),weeksToMonth:Math.floor(this.totalSecsLeft/60/60/24/7)%4,months:Math.floor(this.totalSecsLeft/60/60/24/30.4368),years:Math.abs(this.finalDate.getFullYear()-d.getFullYear()),totalDays:Math.floor(this.totalSecsLeft/60/60/24),totalHours:Math.floor(this.totalSecsLeft/60/60),totalMinutes:Math.floor(this.totalSecsLeft/60),totalSeconds:this.totalSecsLeft},this.options.elapse||0!==this.totalSecsLeft?this.dispatchEvent("update"):(this.stop(),this.dispatchEvent("finish")))},dispatchEvent:function(b){var c=a.Event(b+".countdown");c.finalDate=this.finalDate,c.elapsed=this.elapsed,c.offset=a.extend({},this.offset),c.strftime=d(this.offset),this.$el.trigger(c)}}),a.fn.countdown=function(){var b=Array.prototype.slice.call(arguments,0);return this.each(function(){var c=a(this).data("countdown-instance");if(void 0!==c){var d=f[c],e=b[0];j.prototype.hasOwnProperty(e)?d[e].apply(d,b.slice(1)):null===String(e).match(/^[$A-Z_][0-9A-Z_$]*$/i)?(d.setFinalDate.call(d,e),d.start()):a.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi,e))}else new j(this,b[0],b[1])})}}); -------------------------------------------------------------------------------- /src/main/webapp/assets/js/vendor/imagesloaded.pkgd.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * imagesLoaded PACKAGED v4.1.4 3 | * JavaScript is all like "You images are done yet or what?" 4 | * MIT License 5 | */ 6 | 7 | !function(e,t){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",t):"object"==typeof module&&module.exports?module.exports=t():e.EvEmitter=t()}("undefined"!=typeof window?window:this,function(){function e(){}var t=e.prototype;return t.on=function(e,t){if(e&&t){var i=this._events=this._events||{},n=i[e]=i[e]||[];return n.indexOf(t)==-1&&n.push(t),this}},t.once=function(e,t){if(e&&t){this.on(e,t);var i=this._onceEvents=this._onceEvents||{},n=i[e]=i[e]||{};return n[t]=!0,this}},t.off=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){var n=i.indexOf(t);return n!=-1&&i.splice(n,1),this}},t.emitEvent=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){i=i.slice(0),t=t||[];for(var n=this._onceEvents&&this._onceEvents[e],o=0;o 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | Smart Trade 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 90 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /src/main/webapp/assets/richtexteditor/plugins/html2pdf.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | if (!RTE_DefaultConfig.svgCode_html2pdf) { 4 | RTE_DefaultConfig.svgCode_html2pdf = 'PDF' 5 | } 6 | 7 | RTE_DefaultConfig.plugin_html2pdf = RTE_Plugin_Html2PDF; 8 | 9 | function RTE_Plugin_Html2PDF() { 10 | 11 | var scripturl = "https://raw.githack.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.js"; 12 | 13 | var obj = this; 14 | 15 | var config, editor; 16 | 17 | obj.PluginName = "Html2PDF"; 18 | 19 | obj.InitConfig = function (argconfig) { 20 | config = argconfig; 21 | } 22 | obj.InitEditor = function (argeditor) { 23 | editor = argeditor; 24 | 25 | editor.attachEvent("exec_command_html2pdf", function (state, cmd, value) { 26 | console.log(state, cmd, value); 27 | obj.DoHtml2PDF(); 28 | state.returnValue = true; 29 | }); 30 | 31 | editor.toolbarFactoryMap["html2pdf"] = function (cmd) { 32 | //console.log(cmd); 33 | var span = editor.createToolbarButton(cmd); 34 | span.style.backgroundColor = '' 35 | return span; 36 | }; 37 | 38 | } 39 | 40 | function __Append(parent, tagname, csstext, cssclass) { 41 | var tag = parent.ownerDocument.createElement(tagname); 42 | if (csstext) tag.style.cssText = csstext; 43 | if (cssclass) tag.className = cssclass; 44 | parent.appendChild(tag); 45 | return tag; 46 | } 47 | 48 | 49 | function dataURLToBlob(dataurl) { 50 | var arr = dataurl.split(','); 51 | var mime = arr[0].match(/:(.*?);/)[1]; 52 | var bstr = atob(arr[1]); 53 | var n = bstr.length; 54 | var u8arr = new Uint8Array(n); 55 | while (n--) { 56 | u8arr[n] = bstr.charCodeAt(n); 57 | } 58 | return new Blob([u8arr], { type: mime }); 59 | } 60 | 61 | obj.DoHtml2PDF = function () { 62 | 63 | var dialoginner = editor.createDialog("Html2PDF", "rte-dialog-html2pdf"); 64 | 65 | var div2 = __Append(dialoginner, "div", "position:relative;text-align:center;"); 66 | 67 | div2.innerHTML = "Loading..."; 68 | 69 | var imgrect = __Append(dialoginner, "div", "position:relative;text-align:center;") 70 | 71 | window.html2pdf_callback = function (win) { 72 | 73 | if (!win.html2pdf) { 74 | div2.innerHTML = "Failed to load script."; 75 | return; 76 | } 77 | 78 | div2.innerHTML = "Exporting..."; 79 | 80 | var opt = { 81 | margin: 0.5, 82 | filename: 'myfile.pdf', 83 | image: { type: 'jpeg', quality: 0.98 }, 84 | html2canvas: { scale: 2 }, 85 | jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' } 86 | }; 87 | 88 | var promimg = win.html2pdf().set(opt).from(win.document.body).outputImg(); 89 | promimg.then(function (img) { 90 | 91 | var dataurl = img.getAttribute('src'); 92 | if (dataurl.indexOf("base64") == -1) { 93 | div2.innerHTML = "Error, no data."; 94 | return; 95 | } 96 | 97 | var imgblob = dataURLToBlob(dataurl); 98 | console.log(imgblob); 99 | var imgurl = URL.createObjectURL(imgblob); 100 | img.setAttribute("src", imgurl); 101 | 102 | var prom = win.html2pdf().set(opt).from(win.document.body).outputPdf(); 103 | prom.then(function (str) { 104 | 105 | console.log("done", str.length) 106 | 107 | var bin = new Array(str.length); 108 | for (var i = 0; i < str.length; i++) 109 | bin[i] = str.charCodeAt(i); 110 | var blob = new Blob([new Uint8Array(bin)], { type: "application/pdf" }) 111 | var url = URL.createObjectURL(blob); 112 | div2.innerHTML = Math.ceil(str.length / 1024) + "KB Exported
Download PDF"; 113 | 114 | var pdflink = div2.querySelector("a"); 115 | 116 | var date = new Date(); 117 | var ymd = String(date.getFullYear() * 10000 + (date.getMonth() + 1) * 100 + date.getDate()).substring(2); 118 | var hms = String(1000000 + date.getHours() * 10000 + date.getMinutes() * 100 + date.getSeconds()).substring(1); 119 | pdflink.download = "Export-" + ymd + "-" + hms + ".pdf"; 120 | 121 | //a.rel = 'noopener' 122 | 123 | pdflink.click(); 124 | 125 | img.style.cssText = "max-width:300px;max-height:200px;margin:5px;padding:10px;border:solid 1px #eee;box-shadow:2px 2px 6px #eee" 126 | imgrect.appendChild(img) 127 | 128 | __Append(imgrect, "br"); 129 | var imglink = __Append(imgrect, "a"); 130 | imglink.setAttribute("href", imgurl); 131 | imglink.setAttribute("target", "_blank"); 132 | imglink.download = "Export-" + ymd + "-" + hms + ".jpg"; 133 | imglink.innerText = "Download Img"; 134 | 135 | //dialoginner.close(); 136 | 137 | }).catch(function (x) { 138 | console.error(x); 139 | }) 140 | 141 | }).catch(function (x) { 142 | console.error(x); 143 | }) 144 | 145 | 146 | } 147 | 148 | var div1 = __Append(dialoginner, "div", "position:relative;text-align:center;"); 149 | 150 | iframe = __Append(div1, "iframe", "align-self:center;flex:99;width:100%;height:0px;border:0px;", "rte-editable"); 151 | iframe.contentDocument.open("text/html"); 152 | iframe.contentDocument.write("" 153 | + "" 154 | + editor.getHTMLCode() + "" 155 | + "") 156 | iframe.contentDocument.close(); 157 | 158 | } 159 | } 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /src/main/webapp/assets/js/index.js: -------------------------------------------------------------------------------- 1 | window.addEventListener("load", async () => { 2 | Notiflix.Loading.pulse("Wait...", { 3 | clickToClose: false, 4 | svgColor: '#0284c7' 5 | }); 6 | try { 7 | await loadAllBrands(); 8 | await loadNewArrivals(); 9 | } finally { 10 | Notiflix.Loading.remove(); 11 | } 12 | }); 13 | 14 | async function loadNewArrivals() { 15 | try { 16 | const response = await fetch("api/data/new-arrivals"); 17 | if (response.ok) { 18 | const data = await response.json(); 19 | renderingNewArrivals(data.newArrivals); 20 | } else { 21 | Notiflix.Notify.failure("Product data loading failed!", { 22 | position: 'center-top' 23 | }); 24 | } 25 | } catch (e) { 26 | Notiflix.Notify.failure(e.message, { 27 | position: 'center-top' 28 | }); 29 | } 30 | } 31 | 32 | function renderingNewArrivals(productList) { 33 | console.log(productList); 34 | const newArrivalProductContainer = document.getElementById("new-arrival-product-container"); 35 | newArrivalProductContainer.innerHTML = ""; 36 | productList.forEach((product) => { 37 | product.stockDTOList.forEach((stock) => { 38 | newArrivalProductContainer.innerHTML += `
39 |
40 |
41 | 42 | Product Images 45 | Product Images 47 | 48 | 49 |
50 | 55 |
56 |
57 |
58 |
59 |
${product.title}
60 |
61 | Rs. ${ 62 | new Intl.NumberFormat("en-US", { 63 | minimumFractionDigits: 2, 64 | }).format(stock.price) 65 | } 66 |
67 |
68 |
    69 |
  • 70 | 71 | 72 | 73 |
  • 74 |
75 |
76 |
77 |
78 |
79 |
`; 80 | }); 81 | }); 82 | 83 | refreshAnimations(); 84 | } 85 | 86 | function refreshAnimations() { 87 | if (typeof sal === "function") { 88 | sal(); 89 | } 90 | if (typeof $ !== "undefined") { 91 | $('.categrie-product-activation').slick('refresh'); 92 | } 93 | } 94 | 95 | async function loadAllBrands() { 96 | try { 97 | const productBrandContainer = document.getElementById("product-brand-container"); 98 | productBrandContainer.innerHTML = ""; 99 | const response = await fetch("api/data/brands"); 100 | if (response.ok) { 101 | const data = await response.json(); 102 | data.brands.forEach((brand) => { 103 | productBrandContainer.innerHTML += `
104 | 112 | 113 |
` 114 | }); 115 | refreshAnimations(); 116 | 117 | } else { 118 | Notiflix.Notify.failure("Brands loading failed!", { 119 | position: 'center-top' 120 | }); 121 | } 122 | } catch (e) { 123 | Notiflix.Notify.failure(e.message, { 124 | position: 'center-top' 125 | }); 126 | } 127 | } --------------------------------------------------------------------------------