updated myself
6
pom.xml
@ -69,7 +69,11 @@
|
|||||||
<artifactId>spring-tx</artifactId>
|
<artifactId>spring-tx</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.chantha.springdemo.Configuration;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||||
|
auth.inMemoryAuthentication().withUser("admin").password("{noop}admin").roles("ADMIN")
|
||||||
|
.and().withUser("dba").password("{noop}dba").roles("DBA")
|
||||||
|
.and().withUser("user").password("{noop}user").roles("USER");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
http.formLogin();
|
||||||
|
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
|
||||||
|
http.authorizeRequests()
|
||||||
|
.antMatchers("/admin/**").hasAnyRole("ADMIN")
|
||||||
|
.antMatchers("/dba/**").hasAnyRole("ADMIN","DBA")
|
||||||
|
.antMatchers("/user/**").hasAnyRole("ADMIN","DBA","USER");
|
||||||
|
http.csrf().disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
package com.chantha.springdemo.controller;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import com.chantha.springdemo.model.Food;
|
|
||||||
import com.chantha.springdemo.service.FoodService;
|
|
||||||
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class HomeController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private final FoodService foodService;
|
|
||||||
|
|
||||||
public HomeController(FoodService foodService) {
|
|
||||||
super();
|
|
||||||
this.foodService = foodService;
|
|
||||||
}
|
|
||||||
@RequestMapping("/home")
|
|
||||||
public String show(Model mod) {
|
|
||||||
List<Food> food=foodService.findFoodLimit();
|
|
||||||
mod.addAttribute("foods", food);
|
|
||||||
return "index";
|
|
||||||
}
|
|
||||||
@PostMapping("/food/update")
|
|
||||||
public String updateProduct(@ModelAttribute(name="food") Food food) {
|
|
||||||
foodService.saveFood(food);
|
|
||||||
return "redirect:/home";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/food/delete/{id}")
|
|
||||||
public String deleteFoodById(@PathVariable("id") int id) {
|
|
||||||
foodService.deleteFoodById(id);
|
|
||||||
return "redirect:/home";
|
|
||||||
}
|
|
||||||
@RequestMapping(value="/food/add",method=RequestMethod.POST)
|
|
||||||
public String addProduct(@ModelAttribute(name="food") Food food) {
|
|
||||||
foodService.saveFood(food);
|
|
||||||
return "redirect:/home";
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.chantha.springdemo.controller;
|
||||||
|
|
||||||
|
import com.chantha.springdemo.model.Product;
|
||||||
|
import com.chantha.springdemo.service.ProductService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class MainController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final ProductService productService;
|
||||||
|
|
||||||
|
public MainController(ProductService productService) {
|
||||||
|
this.productService=productService;
|
||||||
|
}
|
||||||
|
@RequestMapping("/")
|
||||||
|
public String indexPage(Model mod){
|
||||||
|
mod.addAttribute("products",productService.findAllProduct());
|
||||||
|
return "index";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/admin")
|
||||||
|
public String adminPage(Model model){
|
||||||
|
List<Product> products=productService.findAllProduct();
|
||||||
|
model.addAttribute("products",products);
|
||||||
|
return "admin/admin";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/dba")
|
||||||
|
public String dbaPage(){
|
||||||
|
return "dba/dba";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/user")
|
||||||
|
public String userPage(){
|
||||||
|
return "user/user";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.chantha.springdemo.controller;
|
||||||
|
|
||||||
|
import com.chantha.springdemo.model.Product;
|
||||||
|
import com.chantha.springdemo.service.ProductService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class ProductController {
|
||||||
|
@Autowired
|
||||||
|
private final ProductService productService;
|
||||||
|
|
||||||
|
public ProductController(ProductService productService) {
|
||||||
|
this.productService=productService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uploadFile(MultipartFile file, RedirectAttributes attributes) {
|
||||||
|
final String UPLOAD_DIR="E:/Interview/springdemo/src/main/resources/static/img/";
|
||||||
|
// normalize the file path
|
||||||
|
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
|
||||||
|
|
||||||
|
// save the file on the local file system
|
||||||
|
try {
|
||||||
|
Path path = Paths.get(UPLOAD_DIR + LocalDate.now()+fileName);
|
||||||
|
Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@PostMapping("/admin/product/add")
|
||||||
|
public String addProduct(@RequestParam("file") MultipartFile file, @ModelAttribute("product") Product product, RedirectAttributes attributes){
|
||||||
|
try {
|
||||||
|
if(product.getName().equals("")||product.getColor().equals("")) {
|
||||||
|
attributes.addFlashAttribute("message", "Something wrong with your information");
|
||||||
|
return "redirect:/admin";
|
||||||
|
}
|
||||||
|
if(!file.isEmpty()){
|
||||||
|
uploadFile(file,attributes);
|
||||||
|
product.setImg(StringUtils.cleanPath(LocalDate.now()+file.getOriginalFilename()));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
product.setImg("default.jpg");
|
||||||
|
}
|
||||||
|
productService.save(product);
|
||||||
|
return "redirect:/admin";
|
||||||
|
}catch (Exception ex){
|
||||||
|
attributes.addFlashAttribute("message", ex.getMessage());
|
||||||
|
return "redirect:/admin";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@PostMapping("/admin/product/update")
|
||||||
|
public String updateProduct(@RequestParam("file") MultipartFile file, @ModelAttribute("product") Product product, RedirectAttributes attributes){
|
||||||
|
try {
|
||||||
|
if(product.getName().equals("")||product.getColor().equals("")) {
|
||||||
|
attributes.addFlashAttribute("message", "Something wrong with your information");
|
||||||
|
return "redirect:/admin";
|
||||||
|
}
|
||||||
|
if(!file.isEmpty()){
|
||||||
|
uploadFile(file,attributes);
|
||||||
|
product.setImg(StringUtils.cleanPath(LocalDate.now()+file.getOriginalFilename()));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Product p=productService.findById(product.getId());
|
||||||
|
product.setImg(p.getImg());
|
||||||
|
}
|
||||||
|
attributes.addFlashAttribute("message", "Update Successfully");
|
||||||
|
productService.save(product);
|
||||||
|
return "redirect:/admin";
|
||||||
|
}catch (Exception ex){
|
||||||
|
attributes.addFlashAttribute("message", ex.getMessage());
|
||||||
|
return "redirect:/admin";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@RequestMapping("/admin/product/delete/{id}")
|
||||||
|
public String deleteProduct(@PathVariable Long id, RedirectAttributes attributes)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
Product pro=productService.findById(id);
|
||||||
|
productService.deleteById(id);
|
||||||
|
attributes.addFlashAttribute("message","Product name "+pro.getName()+" has delete successfully");
|
||||||
|
return "redirect:/admin";
|
||||||
|
}catch (Exception ex){
|
||||||
|
attributes.addFlashAttribute("message", "Sorry your product not register yet");
|
||||||
|
return "redirect:/admin";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,136 @@
|
|||||||
|
package com.chantha.springdemo.controller;
|
||||||
|
|
||||||
|
import com.chantha.springdemo.model.Product;
|
||||||
|
import com.chantha.springdemo.service.ProductService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/product")
|
||||||
|
public class ProductRestController {
|
||||||
|
|
||||||
|
private ProductService productService;
|
||||||
|
private Map<String,Object> map=null;
|
||||||
|
private HttpStatus status=null;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ProductRestController(ProductService productService) {
|
||||||
|
this.productService = productService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "/findAll",headers = "Accept=application/json")
|
||||||
|
public ResponseEntity<Map<String,Object>> findAllProduct(){
|
||||||
|
List<Product> product=null;
|
||||||
|
map=new HashMap<>();
|
||||||
|
try{
|
||||||
|
product=productService.findAllProduct();
|
||||||
|
if(!product.isEmpty()){
|
||||||
|
map.put("data",product);
|
||||||
|
map.put("message","Get product successfully");
|
||||||
|
map.put("status",true);
|
||||||
|
status=HttpStatus.ACCEPTED;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
map.put("message","Cannot get product");
|
||||||
|
map.put("status",false);
|
||||||
|
status=HttpStatus.NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex){
|
||||||
|
map.put("message","Something is broken");
|
||||||
|
map.put("status",false);
|
||||||
|
status=HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(map, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/save",headers = "Accept=application/json")
|
||||||
|
public ResponseEntity<Map<String,Object>> save(@RequestBody Product product, HttpServletRequest request){
|
||||||
|
map=new HashMap<>();
|
||||||
|
try{
|
||||||
|
productService.save(product);
|
||||||
|
Product pro=productService.findById(product.getId());
|
||||||
|
if(pro != null){
|
||||||
|
map.put("data",product);
|
||||||
|
map.put("message","insert product successfully");
|
||||||
|
map.put("status",true);
|
||||||
|
status=HttpStatus.CREATED;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
map.put("message","Cannot insert product");
|
||||||
|
map.put("status",false);
|
||||||
|
status=HttpStatus.NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex){
|
||||||
|
map.put("message","Something is broken");
|
||||||
|
map.put("status",false);
|
||||||
|
status=HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return new ResponseEntity<Map<String,Object>>(map,status);
|
||||||
|
}
|
||||||
|
@PutMapping(value = "/update",headers = "Accept=application/json")
|
||||||
|
public ResponseEntity<Map<String,Object>> update(@RequestBody Product product, HttpServletRequest request){
|
||||||
|
map=new HashMap<>();
|
||||||
|
try{
|
||||||
|
Product pro=productService.findById(product.getId());
|
||||||
|
if(pro != null){
|
||||||
|
productService.save(product);
|
||||||
|
map.put("data",product);
|
||||||
|
map.put("message","update product successfully");
|
||||||
|
map.put("status",true);
|
||||||
|
status=HttpStatus.ACCEPTED;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
map.put("message","Cannot update product");
|
||||||
|
map.put("status",false);
|
||||||
|
status=HttpStatus.NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex){
|
||||||
|
map.put("message","Something is broken");
|
||||||
|
map.put("status",false);
|
||||||
|
status=HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return new ResponseEntity<Map<String,Object>>(map,status);
|
||||||
|
}
|
||||||
|
@PatchMapping(value = "/delete/{id}",headers = "Accept=application/json")
|
||||||
|
public ResponseEntity<Map<String,Object>> delete(@PathVariable("id") Long id){
|
||||||
|
map=new HashMap<>();
|
||||||
|
try{
|
||||||
|
Product pro=productService.findById(id);
|
||||||
|
if(pro != null){
|
||||||
|
productService.deleteById(id);
|
||||||
|
map.put("message","delete product successfully");
|
||||||
|
map.put("status",true);
|
||||||
|
status=HttpStatus.ACCEPTED;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
map.put("message","Can not delete product");
|
||||||
|
map.put("status",false);
|
||||||
|
status=HttpStatus.NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex){
|
||||||
|
map.put("message","Something is broken");
|
||||||
|
map.put("status",false);
|
||||||
|
status=HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return new ResponseEntity<Map<String,Object>>(map,status);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
76
src/main/java/com/chantha/springdemo/model/Product.java
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package com.chantha.springdemo.model;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="tbProduct")
|
||||||
|
public class Product {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy= GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private double price;
|
||||||
|
private String color;
|
||||||
|
private String img;
|
||||||
|
private String des;
|
||||||
|
|
||||||
|
public Product() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Product(String name, double price, String color, String img, String des) {
|
||||||
|
this.name = name;
|
||||||
|
this.price = price;
|
||||||
|
this.color = color;
|
||||||
|
this.img = img;
|
||||||
|
this.des = des;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrice(double price) {
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(String color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImg() {
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImg(String img) {
|
||||||
|
this.img = img;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDes() {
|
||||||
|
return des;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDes(String des) {
|
||||||
|
this.des = des;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.chantha.springdemo.repositories;
|
||||||
|
|
||||||
|
import com.chantha.springdemo.model.Product;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
|
||||||
|
public interface ProductRepository extends CrudRepository<Product, Long> {
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.chantha.springdemo.service;
|
||||||
|
|
||||||
|
import com.chantha.springdemo.model.Product;
|
||||||
|
import com.chantha.springdemo.repositories.ProductRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ProductService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final ProductRepository productRepository;
|
||||||
|
|
||||||
|
public ProductService(ProductRepository productRepository) {
|
||||||
|
this.productRepository=productRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(Product product){
|
||||||
|
productRepository.save(product);
|
||||||
|
}
|
||||||
|
public List<Product> findAllProduct(){
|
||||||
|
return (List<Product>) productRepository.findAll();
|
||||||
|
}
|
||||||
|
public Product findById(Long id){
|
||||||
|
return productRepository.findById(id).orElse(new Product());
|
||||||
|
}
|
||||||
|
public void deleteById(Long id){
|
||||||
|
productRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -5,3 +5,4 @@ spring.datasource.username=postgres
|
|||||||
spring.datasource.password=postgres
|
spring.datasource.password=postgres
|
||||||
spring.jpa.open-in-view=true
|
spring.jpa.open-in-view=true
|
||||||
server.port=8010
|
server.port=8010
|
||||||
|
server.servlet.session.tracking-modes=cookie
|
||||||
|
After Width: | Height: | Size: 60 KiB |
6
src/main/resources/static/css/bootstrap.min.css
vendored
Normal file
290
src/main/resources/static/css/login.css
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
/* BASIC */
|
||||||
|
|
||||||
|
html {
|
||||||
|
background-color: #56baed;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #92badd;
|
||||||
|
display:inline-block;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
display:inline-block;
|
||||||
|
margin: 40px 8px 10px 8px;
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* STRUCTURE */
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#formContent {
|
||||||
|
-webkit-border-radius: 10px 10px 10px 10px;
|
||||||
|
border-radius: 10px 10px 10px 10px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 30px;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 450px;
|
||||||
|
position: relative;
|
||||||
|
padding: 0px;
|
||||||
|
-webkit-box-shadow: 0 30px 60px 0 rgba(0,0,0,0.3);
|
||||||
|
box-shadow: 0 30px 60px 0 rgba(0,0,0,0.3);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#formFooter {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
border-top: 1px solid #dce8f1;
|
||||||
|
padding: 25px;
|
||||||
|
text-align: center;
|
||||||
|
-webkit-border-radius: 0 0 10px 10px;
|
||||||
|
border-radius: 0 0 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* TABS */
|
||||||
|
|
||||||
|
h2.inactive {
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2.active {
|
||||||
|
color: #0d0d0d;
|
||||||
|
border-bottom: 2px solid #5fbae9;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* FORM TYPOGRAPHY*/
|
||||||
|
|
||||||
|
input[type=button], input[type=submit], input[type=reset] {
|
||||||
|
background-color: #56baed;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 15px 80px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 13px;
|
||||||
|
-webkit-box-shadow: 0 10px 30px 0 rgba(95,186,233,0.4);
|
||||||
|
box-shadow: 0 10px 30px 0 rgba(95,186,233,0.4);
|
||||||
|
-webkit-border-radius: 5px 5px 5px 5px;
|
||||||
|
border-radius: 5px 5px 5px 5px;
|
||||||
|
margin: 5px 20px 40px 20px;
|
||||||
|
-webkit-transition: all 0.3s ease-in-out;
|
||||||
|
-moz-transition: all 0.3s ease-in-out;
|
||||||
|
-ms-transition: all 0.3s ease-in-out;
|
||||||
|
-o-transition: all 0.3s ease-in-out;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=button]:hover, input[type=submit]:hover, input[type=reset]:hover {
|
||||||
|
background-color: #39ace7;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=button]:active, input[type=submit]:active, input[type=reset]:active {
|
||||||
|
-moz-transform: scale(0.95);
|
||||||
|
-webkit-transform: scale(0.95);
|
||||||
|
-o-transform: scale(0.95);
|
||||||
|
-ms-transform: scale(0.95);
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text] {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
border: none;
|
||||||
|
color: #0d0d0d;
|
||||||
|
padding: 15px 32px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 5px;
|
||||||
|
width: 85%;
|
||||||
|
border: 2px solid #f6f6f6;
|
||||||
|
-webkit-transition: all 0.5s ease-in-out;
|
||||||
|
-moz-transition: all 0.5s ease-in-out;
|
||||||
|
-ms-transition: all 0.5s ease-in-out;
|
||||||
|
-o-transition: all 0.5s ease-in-out;
|
||||||
|
transition: all 0.5s ease-in-out;
|
||||||
|
-webkit-border-radius: 5px 5px 5px 5px;
|
||||||
|
border-radius: 5px 5px 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text]:focus {
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: 2px solid #5fbae9;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text]:placeholder {
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
input[type=password] {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
border: none;
|
||||||
|
color: #0d0d0d;
|
||||||
|
padding: 15px 32px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 5px;
|
||||||
|
width: 85%;
|
||||||
|
border: 2px solid #f6f6f6;
|
||||||
|
-webkit-transition: all 0.5s ease-in-out;
|
||||||
|
-moz-transition: all 0.5s ease-in-out;
|
||||||
|
-ms-transition: all 0.5s ease-in-out;
|
||||||
|
-o-transition: all 0.5s ease-in-out;
|
||||||
|
transition: all 0.5s ease-in-out;
|
||||||
|
-webkit-border-radius: 5px 5px 5px 5px;
|
||||||
|
border-radius: 5px 5px 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=password]:focus {
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: 2px solid #5fbae9;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=password]:placeholder {
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ANIMATIONS */
|
||||||
|
|
||||||
|
/* Simple CSS3 Fade-in-down Animation */
|
||||||
|
.fadeInDown {
|
||||||
|
-webkit-animation-name: fadeInDown;
|
||||||
|
animation-name: fadeInDown;
|
||||||
|
-webkit-animation-duration: 1s;
|
||||||
|
animation-duration: 1s;
|
||||||
|
-webkit-animation-fill-mode: both;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes fadeInDown {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transform: translate3d(0, -100%, 0);
|
||||||
|
transform: translate3d(0, -100%, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transform: none;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInDown {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transform: translate3d(0, -100%, 0);
|
||||||
|
transform: translate3d(0, -100%, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transform: none;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simple CSS3 Fade-in Animation */
|
||||||
|
@-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
|
||||||
|
@-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
|
||||||
|
@keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
|
||||||
|
|
||||||
|
.fadeIn {
|
||||||
|
opacity:0;
|
||||||
|
-webkit-animation:fadeIn ease-in 1;
|
||||||
|
-moz-animation:fadeIn ease-in 1;
|
||||||
|
animation:fadeIn ease-in 1;
|
||||||
|
|
||||||
|
-webkit-animation-fill-mode:forwards;
|
||||||
|
-moz-animation-fill-mode:forwards;
|
||||||
|
animation-fill-mode:forwards;
|
||||||
|
|
||||||
|
-webkit-animation-duration:1s;
|
||||||
|
-moz-animation-duration:1s;
|
||||||
|
animation-duration:1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fadeIn.first {
|
||||||
|
-webkit-animation-delay: 0.4s;
|
||||||
|
-moz-animation-delay: 0.4s;
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fadeIn.second {
|
||||||
|
-webkit-animation-delay: 0.6s;
|
||||||
|
-moz-animation-delay: 0.6s;
|
||||||
|
animation-delay: 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fadeIn.third {
|
||||||
|
-webkit-animation-delay: 0.8s;
|
||||||
|
-moz-animation-delay: 0.8s;
|
||||||
|
animation-delay: 0.8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fadeIn.fourth {
|
||||||
|
-webkit-animation-delay: 1s;
|
||||||
|
-moz-animation-delay: 1s;
|
||||||
|
animation-delay: 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simple CSS3 Fade-in Animation */
|
||||||
|
.underlineHover:after {
|
||||||
|
display: block;
|
||||||
|
left: 0;
|
||||||
|
bottom: -10px;
|
||||||
|
width: 0;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #56baed;
|
||||||
|
content: "";
|
||||||
|
transition: width 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underlineHover:hover {
|
||||||
|
color: #0d0d0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underlineHover:hover:after{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* OTHERS */
|
||||||
|
|
||||||
|
*:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#icon {
|
||||||
|
width:60%;
|
||||||
|
}
|
@ -294,4 +294,32 @@ li a:hover {
|
|||||||
.central-body{
|
.central-body{
|
||||||
padding-top: 25%;
|
padding-top: 25%;
|
||||||
}
|
}
|
||||||
|
.card {
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
max-width: 300px;
|
||||||
|
margin: auto;
|
||||||
|
text-align: center;
|
||||||
|
font-family: arial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price {
|
||||||
|
color: grey;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card button {
|
||||||
|
border: none;
|
||||||
|
outline: 0;
|
||||||
|
padding: 12px;
|
||||||
|
color: white;
|
||||||
|
background-color: #000;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card button:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
After Width: | Height: | Size: 143 KiB |
BIN
src/main/resources/static/img/2020-04-29javaagent_sample.png
Normal file
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 148 KiB |
BIN
src/main/resources/static/img/2020-04-30800px-Choeungek2.JPG
Normal file
After Width: | Height: | Size: 125 KiB |
After Width: | Height: | Size: 233 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 319 KiB |
BIN
src/main/resources/static/img/default.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/main/resources/static/img/user.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
7
src/main/resources/static/js/bootstrap.min.js
vendored
Normal file
4
src/main/resources/static/js/jquery-2.2.3.min.js
vendored
Normal file
401
src/main/resources/static/js/jquery.mycart.js
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
* jQuery myCart - v1.7 - 2018-03-07
|
||||||
|
* http://asraf-uddin-ahmed.github.io/
|
||||||
|
* Copyright (c) 2017 Asraf Uddin Ahmed; Licensed None
|
||||||
|
*/
|
||||||
|
// function print_current_page(){
|
||||||
|
// window.print();
|
||||||
|
// }
|
||||||
|
|
||||||
|
function print_current_page() {
|
||||||
|
window.print();
|
||||||
|
var x = document.getElementById('hide_product');
|
||||||
|
x.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
(function ($) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var OptionManager = (function () {
|
||||||
|
var objToReturn = {};
|
||||||
|
|
||||||
|
var _options = null;
|
||||||
|
var DEFAULT_OPTIONS = {
|
||||||
|
currencySymbol: '$',
|
||||||
|
classCartIcon: 'my-cart-icon',
|
||||||
|
classCartBadge: 'my-cart-badge',
|
||||||
|
classProductQuantity: 'my-product-quantity',
|
||||||
|
classProductRemove: 'my-product-remove',
|
||||||
|
classCheckoutCart: 'my-cart-checkout',
|
||||||
|
affixCartIcon: true,
|
||||||
|
showCheckoutModal: true,
|
||||||
|
numberOfDecimals: 2,
|
||||||
|
cartItems: null,
|
||||||
|
clickOnAddToCart: function ($addTocart) {},
|
||||||
|
afterAddOnCart: function (products, totalPrice, totalQuantity) {},
|
||||||
|
clickOnCartIcon: function ($cartIcon, products, totalPrice, totalQuantity) {},
|
||||||
|
checkoutCart: function (products, totalPrice, totalQuantity) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
getDiscountPrice: function (products, totalPrice, totalQuantity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var loadOptions = function (customOptions) {
|
||||||
|
_options = $.extend({}, DEFAULT_OPTIONS);
|
||||||
|
ProductManager.clearProduct();
|
||||||
|
if (typeof customOptions === 'object') {
|
||||||
|
$.extend(_options, customOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var getOptions = function () {
|
||||||
|
return _options;
|
||||||
|
};
|
||||||
|
|
||||||
|
objToReturn.loadOptions = loadOptions;
|
||||||
|
objToReturn.getOptions = getOptions;
|
||||||
|
return objToReturn;
|
||||||
|
}());
|
||||||
|
|
||||||
|
var MathHelper = (function () {
|
||||||
|
var objToReturn = {};
|
||||||
|
var getRoundedNumber = function (number) {
|
||||||
|
if (isNaN(number)) {
|
||||||
|
throw new Error('Parameter is not a Number');
|
||||||
|
}
|
||||||
|
number = number * 1;
|
||||||
|
var options = OptionManager.getOptions();
|
||||||
|
return number.toFixed(options.numberOfDecimals);
|
||||||
|
};
|
||||||
|
objToReturn.getRoundedNumber = getRoundedNumber;
|
||||||
|
return objToReturn;
|
||||||
|
}());
|
||||||
|
|
||||||
|
var ProductManager = (function () {
|
||||||
|
var objToReturn = {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
PRIVATE
|
||||||
|
*/
|
||||||
|
localStorage.products = localStorage.products ? localStorage.products : "";
|
||||||
|
var getIndexOfProduct = function (id) {
|
||||||
|
var productIndex = -1;
|
||||||
|
var products = getAllProducts();
|
||||||
|
$.each(products, function (index, value) {
|
||||||
|
if (value.id == id) {
|
||||||
|
productIndex = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return productIndex;
|
||||||
|
};
|
||||||
|
var setAllProducts = function (products) {
|
||||||
|
localStorage.products = JSON.stringify(products);
|
||||||
|
};
|
||||||
|
var addProduct = function (id, name, summary, price, quantity, image) {
|
||||||
|
var products = getAllProducts();
|
||||||
|
products.push({
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
summary: summary,
|
||||||
|
price: price,
|
||||||
|
quantity: quantity,
|
||||||
|
image: image
|
||||||
|
});
|
||||||
|
setAllProducts(products);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
PUBLIC
|
||||||
|
*/
|
||||||
|
var getAllProducts = function () {
|
||||||
|
try {
|
||||||
|
var products = JSON.parse(localStorage.products);
|
||||||
|
return products;
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var updatePoduct = function (id, quantity) {
|
||||||
|
var productIndex = getIndexOfProduct(id);
|
||||||
|
if (productIndex < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var products = getAllProducts();
|
||||||
|
products[productIndex].quantity = typeof quantity === "undefined" ? products[productIndex].quantity * 1 + 1 : quantity;
|
||||||
|
setAllProducts(products);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
var setProduct = function (id, name, summary, price, quantity, image) {
|
||||||
|
if (typeof id === "undefined") {
|
||||||
|
console.error("id required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typeof name === "undefined") {
|
||||||
|
console.error("name required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typeof image === "undefined") {
|
||||||
|
console.error("image required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$.isNumeric(price)) {
|
||||||
|
console.error("price is not a number");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$.isNumeric(quantity)) {
|
||||||
|
console.error("quantity is not a number");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
summary = typeof summary === "undefined" ? "" : summary;
|
||||||
|
|
||||||
|
if (!updatePoduct(id)) {
|
||||||
|
addProduct(id, name, summary, price, quantity, image);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var clearProduct = function () {
|
||||||
|
setAllProducts([]);
|
||||||
|
};
|
||||||
|
var removeProduct = function (id) {
|
||||||
|
var products = getAllProducts();
|
||||||
|
products = $.grep(products, function (value, index) {
|
||||||
|
return value.id != id;
|
||||||
|
});
|
||||||
|
setAllProducts(products);
|
||||||
|
};
|
||||||
|
var getTotalQuantity = function () {
|
||||||
|
var total = 0;
|
||||||
|
var products = getAllProducts();
|
||||||
|
$.each(products, function (index, value) {
|
||||||
|
total += value.quantity * 1;
|
||||||
|
});
|
||||||
|
return total;
|
||||||
|
};
|
||||||
|
var getTotalPrice = function () {
|
||||||
|
var products = getAllProducts();
|
||||||
|
var total = 0;
|
||||||
|
$.each(products, function (index, value) {
|
||||||
|
total += value.quantity * value.price;
|
||||||
|
total = MathHelper.getRoundedNumber(total) * 1;
|
||||||
|
});
|
||||||
|
return total;
|
||||||
|
};
|
||||||
|
|
||||||
|
objToReturn.getAllProducts = getAllProducts;
|
||||||
|
objToReturn.updatePoduct = updatePoduct;
|
||||||
|
objToReturn.setProduct = setProduct;
|
||||||
|
objToReturn.clearProduct = clearProduct;
|
||||||
|
objToReturn.removeProduct = removeProduct;
|
||||||
|
objToReturn.getTotalQuantity = getTotalQuantity;
|
||||||
|
objToReturn.getTotalPrice = getTotalPrice;
|
||||||
|
return objToReturn;
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
var loadMyCartEvent = function (targetSelector) {
|
||||||
|
|
||||||
|
var options = OptionManager.getOptions();
|
||||||
|
var $cartIcon = $("." + options.classCartIcon);
|
||||||
|
var $cartBadge = $("." + options.classCartBadge);
|
||||||
|
var classProductQuantity = options.classProductQuantity;
|
||||||
|
var classProductRemove = options.classProductRemove;
|
||||||
|
var classCheckoutCart = options.classCheckoutCart;
|
||||||
|
|
||||||
|
var idCartModal = 'my-cart-modal';
|
||||||
|
var idCartTable = 'my-cart-table';
|
||||||
|
var idGrandTotal = 'my-cart-grand-total';
|
||||||
|
var idEmptyCartMessage = 'my-cart-empty-message';
|
||||||
|
var idDiscountPrice = 'my-cart-discount-price';
|
||||||
|
var classProductTotal = 'my-product-total';
|
||||||
|
var classAffixMyCartIcon = 'my-cart-icon-affix';
|
||||||
|
|
||||||
|
|
||||||
|
if (options.cartItems && options.cartItems.constructor === Array) {
|
||||||
|
ProductManager.clearProduct();
|
||||||
|
$.each(options.cartItems, function () {
|
||||||
|
ProductManager.setProduct(this.id, this.name, this.summary, this.price, this.quantity, this.image);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$cartBadge.text(ProductManager.getTotalQuantity());
|
||||||
|
|
||||||
|
if (!$("#" + idCartModal).length) {
|
||||||
|
$('body').append(
|
||||||
|
'<div class="modal fade " id="' + idCartModal + '" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">' +
|
||||||
|
'<div class="modal-dialog" role="document">' +
|
||||||
|
'<div class="modal-content ">' +
|
||||||
|
'<div class="modal-header hide_product">' +
|
||||||
|
'<button type="button" class="close hide_product" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||||
|
'<h4 class="modal-title hide_product" id="myModalLabel"><span class="glyphicon glyphicon-shopping-cart hide_product"></span> My Cart</h4>' +
|
||||||
|
'</div>' +
|
||||||
|
'<div class="modal-body">' +
|
||||||
|
'<table class="table table-hover table-responsive" id="' + idCartTable + '"></table>' +
|
||||||
|
'</div>' +
|
||||||
|
'<div class="modal-footer hide_product">' +
|
||||||
|
'<button class="btn btn-success hide_product" style="margint-top:10px!important;" onclick="print_current_page()">Print this page</button>' +
|
||||||
|
'<button type="button" class="btn btn-primary ' + classCheckoutCart + '" >Checkout</button>' +
|
||||||
|
'<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var drawTable = function () {
|
||||||
|
var $cartTable = $("#" + idCartTable);
|
||||||
|
$cartTable.empty();
|
||||||
|
|
||||||
|
var products = ProductManager.getAllProducts();
|
||||||
|
$.each(products, function () {
|
||||||
|
var total = this.quantity * this.price;
|
||||||
|
$cartTable.append(
|
||||||
|
'<tr title="' + this.summary + '" data-id="' + this.id + '" data-price="' + this.price + '">' +
|
||||||
|
'<td class="text-center" style="width: 30px;"><img width="30px" height="30px" src="' + this.image + '"/></td>' +
|
||||||
|
'<td>' + this.name + '</td>' +
|
||||||
|
'<td title="Unit Price" class="text-right">' + options.currencySymbol + MathHelper.getRoundedNumber(this.price) + '</td>' +
|
||||||
|
'<td title="Quantity"><input type="number" min="1" style="width: 70px;" class="' + classProductQuantity + '" value="' + this.quantity + '"/></td>' +
|
||||||
|
'<td title="Total" class="text-right ' + classProductTotal + '">' + options.currencySymbol + MathHelper.getRoundedNumber(total) + '</td>' +
|
||||||
|
'<td title="Remove from Cart" class="text-center" style="width: 30px;"><a href="javascript:void(0);" class="btn btn-xs btn-danger ' + classProductRemove + '">X</a></td>' +
|
||||||
|
'</tr>'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
$cartTable.append(products.length ?
|
||||||
|
'<tr>' +
|
||||||
|
'<td></td>' +
|
||||||
|
'<td><strong>Total</strong></td>' +
|
||||||
|
'<td></td>' +
|
||||||
|
'<td></td>' +
|
||||||
|
'<td class="text-right"><strong id="' + idGrandTotal + '"></strong></td>' +
|
||||||
|
'<td></td>' +
|
||||||
|
'</tr>' :
|
||||||
|
'<div class="alert alert-danger" role="alert" id="' + idEmptyCartMessage + '">Your cart is empty</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
var discountPrice = options.getDiscountPrice(products, ProductManager.getTotalPrice(), ProductManager.getTotalQuantity());
|
||||||
|
if (products.length && discountPrice !== null) {
|
||||||
|
$cartTable.append(
|
||||||
|
'<tr style="color: red">' +
|
||||||
|
'<td></td>' +
|
||||||
|
'<td><strong>Total (including discount)</strong></td>' +
|
||||||
|
'<td></td>' +
|
||||||
|
'<td></td>' +
|
||||||
|
'<td class="text-right"><strong id="' + idDiscountPrice + '"></strong></td>' +
|
||||||
|
'<td></td>' +
|
||||||
|
'</tr>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
showGrandTotal();
|
||||||
|
showDiscountPrice();
|
||||||
|
};
|
||||||
|
var showModal = function () {
|
||||||
|
drawTable();
|
||||||
|
$("#" + idCartModal).modal('show');
|
||||||
|
};
|
||||||
|
var updateCart = function () {
|
||||||
|
$.each($("." + classProductQuantity), function () {
|
||||||
|
var id = $(this).closest("tr").data("id");
|
||||||
|
ProductManager.updatePoduct(id, $(this).val());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var showGrandTotal = function () {
|
||||||
|
$("#" + idGrandTotal).text(options.currencySymbol + MathHelper.getRoundedNumber(ProductManager.getTotalPrice()));
|
||||||
|
};
|
||||||
|
var showDiscountPrice = function () {
|
||||||
|
$("#" + idDiscountPrice).text(options.currencySymbol + MathHelper.getRoundedNumber(options.getDiscountPrice(ProductManager.getAllProducts(), ProductManager.getTotalPrice(), ProductManager.getTotalQuantity())));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
EVENT
|
||||||
|
*/
|
||||||
|
if (options.affixCartIcon) {
|
||||||
|
var cartIconBottom = $cartIcon.offset().top * 1 + $cartIcon.css("height").match(/\d+/) * 1;
|
||||||
|
var cartIconPosition = $cartIcon.css('position');
|
||||||
|
$(window).scroll(function () {
|
||||||
|
$(window).scrollTop() >= cartIconBottom ? $cartIcon.addClass(classAffixMyCartIcon) : $cartIcon.removeClass(classAffixMyCartIcon);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$cartIcon.click(function () {
|
||||||
|
options.showCheckoutModal ? showModal() : options.clickOnCartIcon($cartIcon, ProductManager.getAllProducts(), ProductManager.getTotalPrice(), ProductManager.getTotalQuantity());
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("input", "." + classProductQuantity, function () {
|
||||||
|
var price = $(this).closest("tr").data("price");
|
||||||
|
var id = $(this).closest("tr").data("id");
|
||||||
|
var quantity = $(this).val();
|
||||||
|
|
||||||
|
$(this).parent("td").next("." + classProductTotal).text(options.currencySymbol + MathHelper.getRoundedNumber(price * quantity));
|
||||||
|
ProductManager.updatePoduct(id, quantity);
|
||||||
|
|
||||||
|
$cartBadge.text(ProductManager.getTotalQuantity());
|
||||||
|
showGrandTotal();
|
||||||
|
showDiscountPrice();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('keypress', "." + classProductQuantity, function (evt) {
|
||||||
|
if (evt.keyCode == 38 || evt.keyCode == 40) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
evt.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', "." + classProductRemove, function () {
|
||||||
|
var $tr = $(this).closest("tr");
|
||||||
|
var id = $tr.data("id");
|
||||||
|
$tr.hide(500, function () {
|
||||||
|
ProductManager.removeProduct(id);
|
||||||
|
drawTable();
|
||||||
|
$cartBadge.text(ProductManager.getTotalQuantity());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', "." + classCheckoutCart, function () {
|
||||||
|
var products = ProductManager.getAllProducts();
|
||||||
|
if (!products.length) {
|
||||||
|
$("#" + idEmptyCartMessage).fadeTo('fast', 0.5).fadeTo('fast', 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateCart();
|
||||||
|
var isCheckedOut = options.checkoutCart(ProductManager.getAllProducts(), ProductManager.getTotalPrice(), ProductManager.getTotalQuantity());
|
||||||
|
if (isCheckedOut !== false) {
|
||||||
|
window.print();
|
||||||
|
ProductManager.clearProduct();
|
||||||
|
$cartBadge.text(ProductManager.getTotalQuantity());
|
||||||
|
$("#" + idCartModal).modal("hide");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', targetSelector, function () {
|
||||||
|
var $target = $(this);
|
||||||
|
options.clickOnAddToCart($target);
|
||||||
|
|
||||||
|
var id = $target.data('id');
|
||||||
|
var name = $target.data('name');
|
||||||
|
var summary = $target.data('summary');
|
||||||
|
var price = $target.data('price');
|
||||||
|
var quantity = $target.data('quantity');
|
||||||
|
var image = $target.data('image');
|
||||||
|
|
||||||
|
ProductManager.setProduct(id, name, summary, price, quantity, image);
|
||||||
|
$cartBadge.text(ProductManager.getTotalQuantity());
|
||||||
|
|
||||||
|
options.afterAddOnCart(ProductManager.getAllProducts(), ProductManager.getTotalPrice(), ProductManager.getTotalQuantity());
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$.fn.myCart = function (userOptions) {
|
||||||
|
OptionManager.loadOptions(userOptions);
|
||||||
|
loadMyCartEvent(this.selector);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
})(jQuery);
|
1
src/main/resources/static/js/jquery.mycart.min.js
vendored
Normal file
200
src/main/resources/templates/admin/admin.html
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html
|
||||||
|
xmlns:th="http:/www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
lang="en">
|
||||||
|
|
||||||
|
<head th:replace="fragments/header::headerLink">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<div class="container" th:fragment="table">
|
||||||
|
<!-- Begin Page Content -->
|
||||||
|
<div class="container-fluid" >
|
||||||
|
<div>
|
||||||
|
<!-- Page Heading -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- DataTales Example -->
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
<p th:text="${message}" th:if="${message ne null}" class="alert alert-primary"></p>
|
||||||
|
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#myModal" style="margin-bottom: 10px;">
|
||||||
|
<i class="far fa-edit mr-2"></i>
|
||||||
|
Add product
|
||||||
|
</button>
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="myModal" role="dialog">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
|
||||||
|
<!-- Modal content-->
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">Product</h4>
|
||||||
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="user" id="frmProductAdd" th:action="@{/admin/product/add}" th:object="${product}" enctype="multipart/form-data" method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" id="name" name="name" placeholder="Product..." required pattern="[A-Za-z]">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" id="price" name="price" placeholder="Price" required pattern="[0-9]+(\.[0-9]{1,2})?%?">
|
||||||
|
</div>
|
||||||
|
<select class="form-control" name="color" required>
|
||||||
|
<option>Black</option>
|
||||||
|
<option>Red</option>
|
||||||
|
<option>Green</option>
|
||||||
|
</select>
|
||||||
|
<label for="comment"></label>
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file" class="custom-file-input" id="customFile" name="file">
|
||||||
|
<label class="custom-file-label" for="customFile">Choose file</label>
|
||||||
|
</div>
|
||||||
|
<label for="comment"></label>
|
||||||
|
<div class="form-group">
|
||||||
|
<textarea class="form-control" rows="3" id="comment" name="des"></textarea>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary" type="submit" onclick="check()">Save</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Price</th>
|
||||||
|
<th>Color</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Price</th>
|
||||||
|
<th>Color</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="food:${products}">
|
||||||
|
<td th:text="${food.id}"></td>
|
||||||
|
<td th:text="${food.name}"></td>
|
||||||
|
<td th:text="${food.price}"></td>
|
||||||
|
<td th:text="${food.color}"></td>
|
||||||
|
<td th:text="${food.des}"></td>
|
||||||
|
<td>
|
||||||
|
<img th:src="'/img/'+${food.img}" alt="" class="img-rounded" style="width: 100px; height: 100px;">
|
||||||
|
</td>
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" th:id="${'my'+food.id}" role="dialog">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
|
||||||
|
<!-- Modal content-->
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">Product</h4>
|
||||||
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="user" id="frmFoodEdit" th:action="@{/admin/product/update}" th:object="${product}" th:method="POST" enctype="multipart/form-data">
|
||||||
|
<div class="form-group" th:id="${'food'+food.id}">
|
||||||
|
<input type="text" class="form-control" th:value="${food.id}" id="foodid" name="id" placeholder="Price">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" th:value="${food.name}" id="name" name="name" placeholder="Price" required >
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control " th:value="${food.price}" id="price" name="Price" placeholder="Price" required pattern="[0-9]+(\.[0-9]{1,2})?%?">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" th:value="${food.color}" id="color" name="color" placeholder="Price">
|
||||||
|
</div>
|
||||||
|
<label for="comment"></label>
|
||||||
|
<div class="custom-file" th:id="${'updateFile'+food.id}">
|
||||||
|
<input type="file" class="custom-file-input" id="customFile" name="file">
|
||||||
|
<label class="custom-file-label" for="customFile">Choose file</label>
|
||||||
|
</div>
|
||||||
|
<label for="comment"></label>
|
||||||
|
<div class="form-group">
|
||||||
|
<textarea class="form-control" rows="3" id="comment" name="des" th:value="${food.des}"></textarea>
|
||||||
|
<button class="btn btn-primary" type="submit">Update</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-primary" data-toggle="modal" th:id="${'btn'+ food.id}" th:onclick="'popup('+${food.id}+')'">
|
||||||
|
<i class="far fa-edit mr-2"></i>
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-danger" th:id="${'btndelete'+ food.id}" th:onclick="'deleteFood('+${food.id}+')'">
|
||||||
|
<i class="fas fa-trash-alt mr-2"></i>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /.container-fluid -->
|
||||||
|
</div>
|
||||||
|
<!-- End of Main Content -->
|
||||||
|
|
||||||
|
<!-- Java Script-->
|
||||||
|
<script>
|
||||||
|
function popup(id){
|
||||||
|
document.getElementById("food"+id).style.display="none";
|
||||||
|
var btn=document.getElementById("btn"+id);
|
||||||
|
var file=document.getElementById("updateFile"+id);
|
||||||
|
btn.dataset.target="#my"+id;
|
||||||
|
|
||||||
|
}
|
||||||
|
function deleteFood(id){
|
||||||
|
window.location.replace("/admin/product/delete/"+id+"");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- jQuery-->
|
||||||
|
<script>
|
||||||
|
$(".custom-file-input").on("change", function() {
|
||||||
|
var fileName = $(this).val().split("\\").pop();
|
||||||
|
$(this).siblings(".custom-file-label").addClass("selected").html(fileName);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div th:replace="fragments/footer::footer"></div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
10
src/main/resources/templates/dba/dba.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Database Administrator
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -9,11 +9,12 @@ xmlns:th="http://www.thymeleaf.org">
|
|||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="author" content="">
|
<meta name="author" content="">
|
||||||
<!-- Custom fonts for this template -->
|
<!-- Custom fonts for this template -->
|
||||||
<link th:href="@{/vendor/fontawesome-free/css/all.min.css}" rel="stylesheet" type="text/css">
|
<link th:href="@{/vendor/fontawesome-free/css/all.min.css}" rel="stylesheet">
|
||||||
<link th:href="@{/https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i}" rel="stylesheet">
|
<!-- <link href="/https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">-->
|
||||||
|
|
||||||
<!-- Custom styles for this template -->
|
<!-- Custom styles for this template -->
|
||||||
<link th:href="@{/css/sb-admin-2.min.css}" rel="stylesheet">
|
<link th:href="@{/css/sb-admin-2.min.css}" rel="stylesheet">
|
||||||
|
<link th:href="@{/css/login.css}" rel="stylesheet">
|
||||||
|
|
||||||
<!-- Custom styles for this page -->
|
<!-- Custom styles for this page -->
|
||||||
<link th:href="@{/vendor/datatables/dataTables.bootstrap4.min.css}" rel="stylesheet">
|
<link th:href="@{/vendor/datatables/dataTables.bootstrap4.min.css}" rel="stylesheet">
|
||||||
@ -33,6 +34,7 @@ xmlns:th="http://www.thymeleaf.org">
|
|||||||
|
|
||||||
<!-- Page level custom scripts -->
|
<!-- Page level custom scripts -->
|
||||||
<script th:src="@{/js/demo/datatables-demo.js}"></script>
|
<script th:src="@{/js/demo/datatables-demo.js}"></script>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,180 +1,153 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html
|
<html
|
||||||
xmlns:th="http:/www.thymeleaf.org"
|
xmlns:th="http://www.thymeleaf.org"
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
>
|
||||||
lang="en">
|
|
||||||
|
|
||||||
<head th:replace="fragments/header::headerLink">
|
<head>
|
||||||
|
<title>My Cart</title>
|
||||||
|
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||||
|
<style>
|
||||||
|
.badge-notify{
|
||||||
|
background:red;
|
||||||
|
position:relative;
|
||||||
|
top: -20px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
.my-cart-icon-affix {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Print stylesheet for yourwebsite.com
|
||||||
|
* @version 1.0
|
||||||
|
* @lastmodified 16.06.2016
|
||||||
|
*/
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.hide_product{
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
line-height: 1.3;
|
||||||
|
background: #fff !important;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3, h4 {
|
||||||
|
font-size: 14pt;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
.box{
|
||||||
|
margin-bottom: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<link rel="stylesheet" th:href="@{css/bootstrap.min.css}">
|
||||||
|
<link rel="stylesheet" th:href="@{css/style.css}">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body class="container">
|
||||||
<div>
|
|
||||||
<div class="container" th:fragment="table">
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid" >
|
|
||||||
<div>
|
|
||||||
<!-- Page Heading -->
|
|
||||||
|
|
||||||
|
<div class="page-header hide_product">
|
||||||
|
<h1>Products
|
||||||
|
<div style="float: right; cursor: pointer; ">
|
||||||
|
<a th:href="@{/login}"><span class="glyphicon glyphicon-user "></span></a>
|
||||||
</div>
|
</div>
|
||||||
<!-- DataTales Example -->
|
<div style="float: right; cursor: pointer;">
|
||||||
<div class="card shadow mb-4">
|
<span class="glyphicon glyphicon-shopping-cart my-cart-icon"><span class="badge badge-notify my-cart-badge"></span></span>
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#myModal1" style="margin-bottom: 10px;">
|
|
||||||
<i class="far fa-edit mr-2"></i>
|
|
||||||
Add product
|
|
||||||
</button>
|
|
||||||
<!-- Modal -->
|
|
||||||
<div class="modal fade" id="myModal1" role="dialog">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
|
|
||||||
<!-- Modal content-->
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h4 class="modal-title">Product</h4>
|
|
||||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form class="user" id="frmFoodAdd" th:action="@{/food/add}" th:object="${food}" method="post">
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control form-control-user" id="product" name="name" placeholder="Product...">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control form-control-user" id="price" name="Price" placeholder="Price">
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-primary" type="submit" onclick="check()">Save</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Modal -->
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Price</th>
|
|
||||||
<th>Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Price</th>
|
|
||||||
<th>Action</th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
<tbody>
|
|
||||||
<tr th:each="food:${foods}">
|
|
||||||
<td th:text="${food.id}"></td>
|
|
||||||
<td th:text="${food.name}"></td>
|
|
||||||
<td th:text="${food.price}"></td>
|
|
||||||
<!-- Modal -->
|
|
||||||
<div class="modal fade" th:id="${'my'+food.id}" role="dialog">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
|
|
||||||
<!-- Modal content-->
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h4 class="modal-title">Product</h4>
|
|
||||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form class="user" id="frmFoodEdit" th:action="@{/food/update}" th:object="${food}" th:method="put">
|
|
||||||
<div class="form-group" th:id="${'food'+food.id}">
|
|
||||||
<input type="text" class="form-control form-control-user" th:value="${food.id}" id="foodid" name="id" placeholder="Price">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control form-control-user" th:value="${food.name}" id="name" name="name" placeholder="Price">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control form-control-user" th:value="${food.price}" id="price" name="Price" placeholder="Price">
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-primary" type="submit">Update</button>
|
|
||||||
</form>
|
|
||||||
<!-- Modal -->
|
|
||||||
<div class="modal fade" id="myModal" role="dialog">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
|
|
||||||
<!-- Modal content-->
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h4 class="modal-title">Product</h4>
|
|
||||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form class="user" id="formAddProduct" th:action="@{/burger/addproduct}" th:object="${food}" method="post">
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control form-control-user" id="username" name="name" placeholder="Product...">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control form-control-user" id="password" name="Price" placeholder="Price">
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-primary" type="submit" onclick="check()">Save</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
<!-- <button type="addNewProduct" class="hide_product" name="addNewProduct" id="addNewProduct">Add New Product</button> -->
|
||||||
</div>
|
<div class="row card">
|
||||||
<!-- Modal -->
|
|
||||||
<td>
|
<div class="col-md-3 text-center box hide_product" th:each="product:${products}">
|
||||||
<button type="button" class="btn btn-primary" data-toggle="modal" th:id="${'btn'+ food.id}" th:onclick="'popup('+${food.id}+')'">
|
<img th:src="'img/'+${product.img}" width="150px" height="150px">
|
||||||
<i class="far fa-edit mr-2"></i>
|
<h3><span th:text="${product.name}"></span></h3>
|
||||||
Update
|
<h4><strong th:text="${#numbers.formatCurrency(product.price)}"></strong></h4>
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-danger" th:id="${'btndelete'+ food.id}" th:onclick="'deleteFood('+${food.id}+')'">
|
<button style="margin-bottom: 15px;" class="btn btn-primary my-cart-btn" th:attr="data-id=${product.id},data-name=${product.name},data-summary=${product.des},data-price=${product.price},data-image='img/'+${product.img}" data-quantity="1" >Add to Cart</button>
|
||||||
<i class="fas fa-trash-alt mr-2"></i>
|
|
||||||
Delete
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.container-fluid -->
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
<script>
|
|
||||||
function popup(id){
|
|
||||||
document.getElementById("food"+id).style.display="none";
|
|
||||||
var btn=document.getElementById("btn"+id);
|
|
||||||
btn.dataset.target="#my"+id;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script th:src="@{js/jquery-2.2.3.min.js}"></script>
|
||||||
|
<script type='text/javascript' th:src="@{js/bootstrap.min.js}"></script>
|
||||||
|
<script type='text/javascript' th:src="@{js/jquery.mycart.js}"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
|
||||||
|
var goToCartIcon = function($addTocartBtn){
|
||||||
|
var $cartIcon = $(".my-cart-icon");
|
||||||
|
var $image = $('<img width="30px" height="30px" src="' + $addTocartBtn.data("image") + '"/>').css({"position": "fixed", "z-index": "999"});
|
||||||
|
$addTocartBtn.prepend($image);
|
||||||
|
var position = $cartIcon.position();
|
||||||
|
$image.animate({
|
||||||
|
top: position.top,
|
||||||
|
left: position.left
|
||||||
|
}, 500 , "linear", function() {
|
||||||
|
$image.remove();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function deleteFood(id){
|
|
||||||
window.location.replace("/food/delete/"+id+"");
|
$('.my-cart-btn').myCart({
|
||||||
|
currencySymbol: '$',
|
||||||
|
classCartIcon: 'my-cart-icon',
|
||||||
|
classCartBadge: 'my-cart-badge',
|
||||||
|
classProductQuantity: 'my-product-quantity',
|
||||||
|
classProductRemove: 'my-product-remove',
|
||||||
|
classCheckoutCart: 'my-cart-checkout',
|
||||||
|
affixCartIcon: true,
|
||||||
|
showCheckoutModal: true,
|
||||||
|
numberOfDecimals: 2,
|
||||||
|
|
||||||
|
|
||||||
|
clickOnAddToCart: function($addTocart){
|
||||||
|
goToCartIcon($addTocart);
|
||||||
|
},
|
||||||
|
afterAddOnCart: function(products, totalPrice, totalQuantity) {
|
||||||
|
console.log("afterAddOnCart", products, totalPrice, totalQuantity);
|
||||||
|
},
|
||||||
|
clickOnCartIcon: function($cartIcon, products, totalPrice, totalQuantity) {
|
||||||
|
console.log("cart icon clicked", $cartIcon, products, totalPrice, totalQuantity);
|
||||||
|
},
|
||||||
|
checkoutCart: function(products, totalPrice, totalQuantity) {
|
||||||
|
var checkoutString = "Total Price: " + totalPrice + "\nTotal Quantity: " + totalQuantity;
|
||||||
|
checkoutString += "\n\n id \t name \t summary \t price \t quantity \t image path";
|
||||||
|
$.each(products, function(){
|
||||||
|
checkoutString += ("\n " + this.id + " \t " + this.name + " \t " + this.summary + " \t " + this.price + " \t " + this.quantity + " \t " + this.image);
|
||||||
|
|
||||||
|
});
|
||||||
|
alert(checkoutString)
|
||||||
|
console.log("checking out", products, totalPrice, totalQuantity);
|
||||||
|
},
|
||||||
|
getDiscountPrice: function(products, totalPrice, totalQuantity) {
|
||||||
|
console.log("calculating discount", products, totalPrice, totalQuantity);
|
||||||
|
return totalPrice * 0.5;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#addNewProduct").click(function(event) {
|
||||||
|
var currentElementNo = $(".row").children().length + 1;
|
||||||
|
$(".row").append('<div class="col-md-3 text-center"><img src="images/img_empty.png" width="150px" height="150px"><br>product ' + currentElementNo + ' - <strong>$' + currentElementNo + '</strong><br><button class="btn btn-danger my-cart-btn" data-id="' + currentElementNo + '" data-name="product ' + currentElementNo + '" data-summary="summary ' + currentElementNo + '" data-price="' + currentElementNo + '" data-quantity="1" data-image="images/img_empty.png">Add to Cart</button><a href="#" class="btn btn-info">Details</a></div>')
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<div th:replace="fragments/footer::footer"></div>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
36
src/main/resources/templates/login.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html
|
||||||
|
xmlns:th="http:/www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
lang="en">
|
||||||
|
<head th:replace="fragments/header::headerLink">
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper fadeInDown">
|
||||||
|
<div id="formContent">
|
||||||
|
<!-- Tabs Titles -->
|
||||||
|
|
||||||
|
<!-- Icon -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Login Form -->
|
||||||
|
<form>
|
||||||
|
<input type="text" id="login" class="fadeIn second" name="login" placeholder="login">
|
||||||
|
<input type="password" id="password" class="fadeIn third" name="login" placeholder="password">
|
||||||
|
<input type="submit" class="fadeIn fourth" value="Log In">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Remind Passowrd -->
|
||||||
|
<div id="formFooter">
|
||||||
|
<a class="underlineHover" href="#">Forgot Password?</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<footer>
|
||||||
|
<div th:replace="fragments/footer::footer"></div>
|
||||||
|
</footer>
|
||||||
|
</html>
|
10
src/main/resources/templates/user/user.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
User page
|
||||||
|
</body>
|
||||||
|
</html>
|