diff --git a/pom.xml b/pom.xml index 7cac8d9..ef069ab 100644 --- a/pom.xml +++ b/pom.xml @@ -16,36 +16,82 @@ 1.8 + + + org.springframework + spring-orm + + + + org.hibernate + hibernate-entitymanager + + + + mysql + mysql-connector-java + + + + junit + junit + 4.12 + test + + org.springframework.boot spring-boot-starter-thymeleaf + org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-test + test + + org.springframework.boot spring-boot-devtools runtime - true + + + org.seleniumhq.selenium + selenium-java + test + + + + org.seleniumhq.selenium + htmlunit-driver + test + + + + org.springframework.boot + spring-boot-starter-actuator + + org.projectlombok lombok - true - org.springframework.boot - spring-boot-starter-test - test + org.hibernate.validator + hibernate-validator + 6.0.11.Final - junit - junit - 4.13.2 + org.codehaus.groovy + groovy + 2.4.15 test diff --git a/src/main/java/tacos/HomeController.java b/src/main/java/tacos/HomeController.java deleted file mode 100644 index 3179469..0000000 --- a/src/main/java/tacos/HomeController.java +++ /dev/null @@ -1,12 +0,0 @@ -package tacos; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -public class HomeController { - @GetMapping("/") - public String home() { - return "home"; - } -} diff --git a/src/main/java/tacos/Ingredient.java b/src/main/java/tacos/Ingredient.java new file mode 100644 index 0000000..e6921d7 --- /dev/null +++ b/src/main/java/tacos/Ingredient.java @@ -0,0 +1,21 @@ +package tacos; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@Data +@RequiredArgsConstructor +public class Ingredient { + + private final String id; + private final String name; + private final Type type; + + public enum Type { + WRAP, + PROTEIN, + VEGGIES, + CHEESE, + SAUCE + } +} diff --git a/src/main/java/tacos/Order.java b/src/main/java/tacos/Order.java new file mode 100644 index 0000000..7e2d9e6 --- /dev/null +++ b/src/main/java/tacos/Order.java @@ -0,0 +1,37 @@ +package tacos; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; + +import org.hibernate.validator.constraints.CreditCardNumber; + +import lombok.Data; + +@Data +public class Order { + + @NotBlank(message = "Name is required") + private String name; + + @NotBlank(message = "Street is required") + private String street; + + @NotBlank(message = "City is required") + private String city; + + @NotBlank(message = "State is required") + private String state; + + @NotBlank(message = "Zip code is required") + private String zip; + + @CreditCardNumber(message = "Not a valid credit card number") + private String ccNumber; + + @Pattern(regexp = "^(0[1-9]|1[0-2])([/])([1-9][0-9])$", message = "Must be formatted MM/YY") + private String ccExpiration; + + @Digits(integer = 3, fraction = 0, message = "Invalid CVV") + private String ccCVV; +} \ No newline at end of file diff --git a/src/main/java/tacos/Taco.java b/src/main/java/tacos/Taco.java new file mode 100644 index 0000000..31b37c6 --- /dev/null +++ b/src/main/java/tacos/Taco.java @@ -0,0 +1,19 @@ +package tacos; + +import java.util.List; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import lombok.Data; + +@Data +public class Taco { + + @NotNull + @Size(min = 5, message = "Name must be at least 5 characters long") + private String name; + + @Size(min = 1, message = "You must choose at least 1 ingredient") + private List ingredients; +} \ No newline at end of file diff --git a/src/main/java/tacos/web/DesignTacoController.java b/src/main/java/tacos/web/DesignTacoController.java new file mode 100644 index 0000000..d7d0d1f --- /dev/null +++ b/src/main/java/tacos/web/DesignTacoController.java @@ -0,0 +1,65 @@ +package tacos.web; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import javax.validation.Valid; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import lombok.extern.slf4j.Slf4j; +import tacos.Ingredient; +import tacos.Ingredient.Type; +import tacos.Taco; + +@Slf4j +@Controller +@RequestMapping("/design") +public class DesignTacoController { + + @ModelAttribute + public void addIngredientsToModel(Model model) { + List ingredients = Arrays.asList(new Ingredient("FLTO", "Flour Tortilla", Type.WRAP), + new Ingredient("COTO", "Corn Tortilla", Type.WRAP), new Ingredient("GRBF", "Ground Beef", Type.PROTEIN), + new Ingredient("CARN", "Carnitas", Type.PROTEIN), new Ingredient("TMTO", "Diced Tomatoes", Type.VEGGIES), + new Ingredient("LETC", "Lettuce", Type.VEGGIES), new Ingredient("CHED", "Cheddar", Type.CHEESE), + new Ingredient("JACK", "Monterrey Jack", Type.CHEESE), new Ingredient("SLSA", "Salsa", Type.SAUCE), + new Ingredient("SRCR", "Sour Cream", Type.SAUCE)); + + Type[] types = Ingredient.Type.values(); + for (Type type : types) { + model.addAttribute(type.toString() + .toLowerCase(), filterByType(ingredients, type)); + } + } + + @GetMapping + public String showDesignForm(Model model) { + model.addAttribute("design", new Taco()); + return "design"; + } + + @PostMapping + public String processDesign(@Valid @ModelAttribute("design") Taco design, Errors errors) { + if (errors.hasErrors()) { + return "design"; + } + log.info("Processing design: " + design); + + return "redirect:/orders/current"; + } + + private List filterByType(List ingredients, Type type) { + return ingredients.stream() + .filter(x -> x.getType() + .equals(type)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/tacos/web/OrderController.java b/src/main/java/tacos/web/OrderController.java new file mode 100644 index 0000000..e39985e --- /dev/null +++ b/src/main/java/tacos/web/OrderController.java @@ -0,0 +1,35 @@ +package tacos.web; + +import javax.validation.Valid; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import lombok.extern.slf4j.Slf4j; +import tacos.Order; + +@Slf4j +@Controller +@RequestMapping("/orders") +public class OrderController { + + @GetMapping("/current") + public String orderForm(Model model) { + model.addAttribute("order", new Order()); + return "orderForm"; + } + + @PostMapping + public String processOrder(@Valid Order order, Errors errors) { + if (errors.hasErrors()) { + return "orderForm"; + } + + log.info("Order submitted: " + order); + return "redirect:/"; + } +} \ No newline at end of file diff --git a/src/main/java/tacos/web/WebConfig.java b/src/main/java/tacos/web/WebConfig.java new file mode 100644 index 0000000..59d2b98 --- /dev/null +++ b/src/main/java/tacos/web/WebConfig.java @@ -0,0 +1,15 @@ +package tacos.web; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/") + .setViewName("home"); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/static/images/TacoCloud.png b/src/main/resources/static/images/TacoCloud.png index ca7b00f..5d78239 100644 Binary files a/src/main/resources/static/images/TacoCloud.png and b/src/main/resources/static/images/TacoCloud.png differ diff --git a/src/main/resources/static/styles.css b/src/main/resources/static/styles.css new file mode 100644 index 0000000..a2eaa4e --- /dev/null +++ b/src/main/resources/static/styles.css @@ -0,0 +1,29 @@ +div.ingredient-group:nth-child(odd) { + float: left; + padding-right: 20px; +} + +div.ingredient-group:nth-child(even) { + float: left; + padding-right: 0; +} + +div.ingredient-group { + width: 50%; +} + +.grid:after { + content: ""; + display: table; + clear: both; +} + +*, *:after, *:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +span.validationError { + color: red; +} \ No newline at end of file diff --git a/src/main/resources/templates/design.html b/src/main/resources/templates/design.html new file mode 100644 index 0000000..0884c64 --- /dev/null +++ b/src/main/resources/templates/design.html @@ -0,0 +1,76 @@ + + + + Taco Cloud + + + + +

Design your taco!

+ + +
+ + Ingredient Error + +
+
+

Designate your wrap:

+
+ + INGREDIENT
+
+
+ +
+

Pick your protein:

+
+ + INGREDIENT
+
+
+ +
+

Choose your cheese:

+
+ + INGREDIENT
+
+
+ +
+

Determine your veggies:

+
+ + INGREDIENT
+
+
+ +
+

Select your sauce:

+
+ + INGREDIENT
+
+
+
+ +
+ + +

Name your taco creation:

+ + XXX + Name Error +
+ + +
+
+ + diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html index a5ceb70..f4ae9d3 100644 --- a/src/main/resources/templates/home.html +++ b/src/main/resources/templates/home.html @@ -1,11 +1,14 @@ - - - - Taco Cloud - - -

Welcome to...

- - + + + Taco Cloud + + + +

Welcome to...

+ + + Design a taco + \ No newline at end of file diff --git a/src/main/resources/templates/orderForm.html b/src/main/resources/templates/orderForm.html new file mode 100644 index 0000000..77021bd --- /dev/null +++ b/src/main/resources/templates/orderForm.html @@ -0,0 +1,85 @@ + + + + Taco Cloud + + + + + +
+

Order your taco creations!

+ + + Design another taco
+ +
+ + Please correct the problems below and resubmit. + +
+ +

Deliver my taco masterpieces to...

+ + + Name Error +
+ + + + Street Error +
+ + + + City Error +
+ + + + State Error +
+ + + + Zip Error +
+ +

Here's how I'll pay...

+ + + CC Num Error +
+ + + + CC Num Error +
+ + + + CC Num Error +
+ + +
+ + + diff --git a/src/test/java/tacos/HomeControllerTest.java b/src/test/java/tacos/HomeControllerTest.java deleted file mode 100644 index fa791c6..0000000 --- a/src/test/java/tacos/HomeControllerTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package tacos; - -import static org.hamcrest.Matchers.containsString; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -@RunWith(SpringRunner.class) -@WebMvcTest(HomeController.class) -public class HomeControllerTest { - @Autowired - private MockMvc mockMvc; - - @Test - public void testHomePage() throws Exception { - mockMvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(view().name("home")) - .andExpect(content().string(containsString("Welcome to..."))); - } -} \ No newline at end of file