Merge remote-tracking branch 'origin/main' into fix-item-input
This commit is contained in:
3
.env.example
Normal file
3
.env.example
Normal file
@@ -0,0 +1,3 @@
|
||||
SPOONACCULAR_API_URL=
|
||||
SPOONACCULAR_API_KEY=
|
||||
SPOONACCULAR_API_SEARCH_RANKING=
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -92,3 +92,9 @@ out
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
frontend/src/index.js
|
||||
|
||||
.env
|
||||
|
||||
.DS_Store
|
||||
|
||||
backend/src/resources/application.yml
|
||||
|
||||
20
backend/src/main/spoonaccular/APIAuthentication.java
Normal file
20
backend/src/main/spoonaccular/APIAuthentication.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package spoonaccular;
|
||||
|
||||
import io.github.cdimascio.dotenv.Dotenv;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class APIAuthentication {
|
||||
|
||||
private static final Dotenv dotenv = Dotenv.configure().ignoreIfMissing().ignoreIfMalformed().load();
|
||||
|
||||
private APIAuthentication(){
|
||||
}
|
||||
|
||||
public static Request.Builder addAuthHeaders(Request.Builder builder){
|
||||
return builder
|
||||
.get()
|
||||
.addHeader("X-RapidAPI-Key", dotenv.get("X-RapidAPI-Key"))
|
||||
.addHeader("X-RapidAPI-Host", dotenv.get("X-RapidAPI-Host"));
|
||||
}
|
||||
|
||||
}
|
||||
59
backend/src/main/spoonaccular/RecipeInformation.java
Normal file
59
backend/src/main/spoonaccular/RecipeInformation.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package spoonaccular;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.github.cdimascio.dotenv.Dotenv;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.springframework.stereotype.Component;
|
||||
import spoonaccular.models.recipe_by_ingredient.ExtendedRecipeByIngredient;
|
||||
import spoonaccular.models.recipe_by_ingredient.RecipeByIngredient;
|
||||
import spoonaccular.models.recipe_information.Recipe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class RecipeInformation {
|
||||
|
||||
private final static Dotenv dotenv = Dotenv.configure().ignoreIfMissing().ignoreIfMalformed().load();
|
||||
private final static OkHttpClient client = new OkHttpClient();
|
||||
|
||||
private RecipeInformation(){
|
||||
}
|
||||
|
||||
public static List<Recipe> getRecipeFromIds(List<Integer> ids) throws IOException {
|
||||
String idsString = ids.stream().map(String::valueOf)
|
||||
.collect(Collectors.joining(","));
|
||||
return new ObjectMapper().readValue(queryInformationBulk(idsString).body().string(), new TypeReference<>(){});
|
||||
}
|
||||
|
||||
public static List<ExtendedRecipeByIngredient> getExtendedRecipeFromIds(List<Integer> ids) throws IOException {
|
||||
String idsString = ids.stream().map(String::valueOf)
|
||||
.collect(Collectors.joining(","));
|
||||
return new ObjectMapper().readValue(queryInformationBulk(idsString).body().string(), new TypeReference<>() {});
|
||||
}
|
||||
|
||||
private static Response queryInformationBulk(String idsString) throws IOException {
|
||||
Request request = APIAuthentication.addAuthHeaders(new Request.Builder()
|
||||
.url("https://" + dotenv.get("X-RapidAPI-Host") +
|
||||
"/recipes/informationBulk?ids=" + idsString))
|
||||
.build();
|
||||
return client.newCall(request).execute();
|
||||
}
|
||||
|
||||
public static List<ExtendedRecipeByIngredient> getRecepieByIngredientsExtended(List<RecipeByIngredient> recipeByIngredients) throws IOException {
|
||||
List<Integer> ids = recipeByIngredients.stream().map(RecipeByIngredient::getId).toList();
|
||||
List<ExtendedRecipeByIngredient> extendedRecipeByIngredients = getExtendedRecipeFromIds(ids);
|
||||
Iterator<RecipeByIngredient> recipeByIngredientIterator = recipeByIngredients.iterator();
|
||||
Iterator<ExtendedRecipeByIngredient> extendedRecipeByIngredientIterator = extendedRecipeByIngredients.iterator();
|
||||
while(recipeByIngredientIterator.hasNext() && extendedRecipeByIngredientIterator.hasNext()){
|
||||
extendedRecipeByIngredientIterator.next().addMissingInfo(recipeByIngredientIterator.next());
|
||||
}
|
||||
return extendedRecipeByIngredients;
|
||||
}
|
||||
|
||||
}
|
||||
69
backend/src/main/spoonaccular/RecipeSearch.java
Normal file
69
backend/src/main/spoonaccular/RecipeSearch.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package spoonaccular;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.github.cdimascio.dotenv.Dotenv;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
import spoonaccular.models.recipe_by_ingredient.ExtendedRecipeByIngredient;
|
||||
import spoonaccular.models.recipe_by_ingredient.RecipeByIngredient;
|
||||
import spoonaccular.models.recipe_information.Recipe;
|
||||
import whattocook.models.Item;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@Component
|
||||
public class RecipeSearch {
|
||||
private static final boolean IGNOREPANTRY = true;
|
||||
|
||||
private static final Random rnd = new Random();
|
||||
private static final Dotenv dotenv = Dotenv.configure().ignoreIfMissing().ignoreIfMalformed().load();
|
||||
|
||||
private static final OkHttpClient client = new OkHttpClient();
|
||||
|
||||
private RecipeSearch(){
|
||||
}
|
||||
|
||||
public static List<ExtendedRecipeByIngredient> getForIngridients(Iterable<Item> items, int number) throws java.io.IOException {
|
||||
List<String> itemNames = new LinkedList<>();
|
||||
items.forEach(item -> itemNames.add(item.getName()));
|
||||
String ingridients = String.join(",", itemNames);
|
||||
|
||||
Request request =
|
||||
APIAuthentication.addAuthHeaders(new Request.Builder()
|
||||
.url("https://" + dotenv.get("X-RapidAPI-Host") +
|
||||
"/recipes/findByIngredients?ingredients="
|
||||
+ ingridients + "&number=" + number + "&ignorePantry="
|
||||
+ IGNOREPANTRY + "&ranking=" + dotenv.get("X-RapidAPI-SearchRanking")))
|
||||
.build();
|
||||
|
||||
Response response = client.newCall(request).execute();
|
||||
String responseString = response.body().string();
|
||||
|
||||
List<RecipeByIngredient> recipeByIngredients = new ObjectMapper().readValue(responseString, new TypeReference<>(){});
|
||||
return RecipeInformation.getRecepieByIngredientsExtended(recipeByIngredients);
|
||||
}
|
||||
|
||||
public static ExtendedRecipeByIngredient getOneForIngridients(Iterable<Item> items, int number) throws IOException {
|
||||
return getForIngridients(items, number).get(rnd.nextInt(number));
|
||||
}
|
||||
|
||||
public static List<Recipe> getRandom(List<String> tags, int number) throws java.io.IOException, JSONException {
|
||||
String tagString = String.join(",", tags);
|
||||
Request request = APIAuthentication.addAuthHeaders(new Request.Builder()
|
||||
.url("https://" + dotenv.get("X-RapidAPI-Host") +
|
||||
"/recipes/random?number=" + number + "&tags=" + tagString))
|
||||
.build();
|
||||
|
||||
Response response = client.newCall(request).execute();
|
||||
JSONObject jsonObject = new JSONObject(response.body().string());
|
||||
return new ObjectMapper().readValue(jsonObject.getJSONArray("recipes").toString(), new TypeReference<>(){});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package spoonaccular.models.recipe_by_ingredient;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import spoonaccular.models.recipe_information.Recipe;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ExtendedRecipeByIngredient extends Recipe {
|
||||
|
||||
@JsonProperty("usedIngredientCount")
|
||||
private Integer usedIngredientCount;
|
||||
@JsonProperty("missedIngredientCount")
|
||||
private Integer missedIngredientCount;
|
||||
@JsonProperty("missedIngredients")
|
||||
private List<MissedIngredient> missedIngredients = null;
|
||||
@JsonProperty("usedIngredients")
|
||||
private List<UsedIngredient> usedIngredients = null;
|
||||
|
||||
@JsonProperty("usedIngredientCount")
|
||||
public Integer getUsedIngredientCount() {
|
||||
return usedIngredientCount;
|
||||
}
|
||||
|
||||
@JsonProperty("usedIngredientCount")
|
||||
public void setUsedIngredientCount(Integer usedIngredientCount) {
|
||||
this.usedIngredientCount = usedIngredientCount;
|
||||
}
|
||||
|
||||
@JsonProperty("missedIngredientCount")
|
||||
public Integer getMissedIngredientCount() {
|
||||
return missedIngredientCount;
|
||||
}
|
||||
|
||||
@JsonProperty("missedIngredientCount")
|
||||
public void setMissedIngredientCount(Integer missedIngredientCount) {
|
||||
this.missedIngredientCount = missedIngredientCount;
|
||||
}
|
||||
|
||||
@JsonProperty("missedIngredients")
|
||||
public List<MissedIngredient> getMissedIngredients() {
|
||||
return missedIngredients;
|
||||
}
|
||||
|
||||
@JsonProperty("missedIngredients")
|
||||
public void setMissedIngredients(List<MissedIngredient> missedIngredients) {
|
||||
this.missedIngredients = missedIngredients;
|
||||
}
|
||||
|
||||
@JsonProperty("usedIngredients")
|
||||
public List<UsedIngredient> getUsedIngredients() {
|
||||
return usedIngredients;
|
||||
}
|
||||
|
||||
@JsonProperty("usedIngredients")
|
||||
public void setUsedIngredients(List<UsedIngredient> usedIngredients) {
|
||||
this.usedIngredients = usedIngredients;
|
||||
}
|
||||
|
||||
public void addMissingInfo(RecipeByIngredient recipeByIngredient){
|
||||
this.setMissedIngredientCount(recipeByIngredient.getMissedIngredientCount());
|
||||
this.setUsedIngredientCount(recipeByIngredient.getUsedIngredientCount());
|
||||
this.setMissedIngredients(recipeByIngredient.getMissedIngredients());
|
||||
this.setUsedIngredients(recipeByIngredient.getUsedIngredients());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
package spoonaccular.models.recipe_by_ingredient;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonPropertyOrder({
|
||||
"name"
|
||||
})
|
||||
@Generated("jsonschema2pojo")
|
||||
public class MissedIngredient {
|
||||
|
||||
@JsonProperty("name")
|
||||
private String name;
|
||||
|
||||
@JsonProperty("name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@JsonProperty("name")
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
|
||||
package spoonaccular.models.recipe_by_ingredient;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import java.util.List;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonPropertyOrder({
|
||||
"id",
|
||||
"title",
|
||||
"image",
|
||||
"usedIngredientCount",
|
||||
"missedIngredientCount",
|
||||
"missedIngredients",
|
||||
"usedIngredients",
|
||||
})
|
||||
@Generated("jsonschema2pojo")
|
||||
public class RecipeByIngredient {
|
||||
|
||||
@JsonProperty("id")
|
||||
private Integer id;
|
||||
@JsonProperty("title")
|
||||
private String title;
|
||||
@JsonProperty("image")
|
||||
private String image;
|
||||
@JsonProperty("usedIngredientCount")
|
||||
private Integer usedIngredientCount;
|
||||
@JsonProperty("missedIngredientCount")
|
||||
private Integer missedIngredientCount;
|
||||
@JsonProperty("missedIngredients")
|
||||
private List<MissedIngredient> missedIngredients = null;
|
||||
@JsonProperty("usedIngredients")
|
||||
private List<UsedIngredient> usedIngredients = null;
|
||||
|
||||
@JsonProperty("id")
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@JsonProperty("id")
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@JsonProperty("title")
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@JsonProperty("title")
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@JsonProperty("image")
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
@JsonProperty("image")
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
@JsonProperty("usedIngredientCount")
|
||||
public Integer getUsedIngredientCount() {
|
||||
return usedIngredientCount;
|
||||
}
|
||||
|
||||
@JsonProperty("usedIngredientCount")
|
||||
public void setUsedIngredientCount(Integer usedIngredientCount) {
|
||||
this.usedIngredientCount = usedIngredientCount;
|
||||
}
|
||||
|
||||
@JsonProperty("missedIngredientCount")
|
||||
public Integer getMissedIngredientCount() {
|
||||
return missedIngredientCount;
|
||||
}
|
||||
|
||||
@JsonProperty("missedIngredientCount")
|
||||
public void setMissedIngredientCount(Integer missedIngredientCount) {
|
||||
this.missedIngredientCount = missedIngredientCount;
|
||||
}
|
||||
|
||||
@JsonProperty("missedIngredients")
|
||||
public List<MissedIngredient> getMissedIngredients() {
|
||||
return missedIngredients;
|
||||
}
|
||||
|
||||
@JsonProperty("missedIngredients")
|
||||
public void setMissedIngredients(List<MissedIngredient> missedIngredients) {
|
||||
this.missedIngredients = missedIngredients;
|
||||
}
|
||||
|
||||
@JsonProperty("usedIngredients")
|
||||
public List<UsedIngredient> getUsedIngredients() {
|
||||
return usedIngredients;
|
||||
}
|
||||
|
||||
@JsonProperty("usedIngredients")
|
||||
public void setUsedIngredients(List<UsedIngredient> usedIngredients) {
|
||||
this.usedIngredients = usedIngredients;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
package spoonaccular.models.recipe_by_ingredient;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonPropertyOrder({
|
||||
"name"
|
||||
})
|
||||
@Generated("jsonschema2pojo")
|
||||
public class UsedIngredient {
|
||||
|
||||
@JsonProperty("name")
|
||||
private String name;
|
||||
|
||||
@JsonProperty("name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@JsonProperty("name")
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
package spoonaccular.models.recipe_information;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonPropertyOrder({
|
||||
"name",
|
||||
"measures"
|
||||
})
|
||||
@Generated("jsonschema2pojo")
|
||||
public class ExtendedIngredient {
|
||||
|
||||
@JsonProperty("name")
|
||||
private String name;
|
||||
@JsonProperty("measures")
|
||||
private Measures measures;
|
||||
|
||||
@JsonProperty("name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@JsonProperty("name")
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@JsonProperty("measures")
|
||||
public Measures getMeasures() {
|
||||
return measures;
|
||||
}
|
||||
|
||||
@JsonProperty("measures")
|
||||
public void setMeasures(Measures measures) {
|
||||
this.measures = measures;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
package spoonaccular.models.recipe_information;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonPropertyOrder({
|
||||
"metric"
|
||||
})
|
||||
@Generated("jsonschema2pojo")
|
||||
public class Measures {
|
||||
|
||||
@JsonProperty("metric")
|
||||
private Metric metric;
|
||||
|
||||
@JsonProperty("metric")
|
||||
public Metric getMetric() {
|
||||
return metric;
|
||||
}
|
||||
|
||||
@JsonProperty("metric")
|
||||
public void setMetric(Metric metric) {
|
||||
this.metric = metric;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
package spoonaccular.models.recipe_information;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonPropertyOrder({
|
||||
"amount",
|
||||
"unitShort"
|
||||
})
|
||||
@Generated("jsonschema2pojo")
|
||||
public class Metric {
|
||||
|
||||
@JsonProperty("amount")
|
||||
private Double amount;
|
||||
@JsonProperty("unitShort")
|
||||
private String unitShort;
|
||||
|
||||
@JsonProperty("amount")
|
||||
public Double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
@JsonProperty("amount")
|
||||
public void setAmount(Double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
@JsonProperty("unitShort")
|
||||
public String getUnitShort() {
|
||||
return unitShort;
|
||||
}
|
||||
|
||||
@JsonProperty("unitShort")
|
||||
public void setUnitShort(String unitShort) {
|
||||
this.unitShort = unitShort;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
|
||||
package spoonaccular.models.recipe_information;
|
||||
|
||||
import java.util.List;
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonPropertyOrder({
|
||||
"vegetarian",
|
||||
"vegan",
|
||||
"glutenFree",
|
||||
"dairyFree",
|
||||
"extendedIngredients",
|
||||
"id",
|
||||
"title",
|
||||
"readyInMinutes",
|
||||
"servings",
|
||||
"image",
|
||||
"spoonacularSourceUrl"
|
||||
})
|
||||
@Generated("jsonschema2pojo")
|
||||
public class Recipe {
|
||||
|
||||
@JsonProperty("vegetarian")
|
||||
private Boolean vegetarian;
|
||||
@JsonProperty("vegan")
|
||||
private Boolean vegan;
|
||||
@JsonProperty("glutenFree")
|
||||
private Boolean glutenFree;
|
||||
@JsonProperty("dairyFree")
|
||||
private Boolean diaryFree;
|
||||
@JsonProperty("extendedIngredients")
|
||||
private List<ExtendedIngredient> extendedIngredients = null;
|
||||
@JsonProperty("id")
|
||||
private Integer id;
|
||||
@JsonProperty("title")
|
||||
private String title;
|
||||
@JsonProperty("readyInMinutes")
|
||||
private Integer readyInMinutes;
|
||||
@JsonProperty("servings")
|
||||
private Integer servings;
|
||||
@JsonProperty("image")
|
||||
private String image;
|
||||
@JsonProperty("spoonacularSourceUrl")
|
||||
private String spoonacularSourceUrl;
|
||||
|
||||
@JsonProperty("vegetarian")
|
||||
public Boolean getVegetarian() {
|
||||
return vegetarian;
|
||||
}
|
||||
|
||||
@JsonProperty("vegetarian")
|
||||
public void setVegetarian(Boolean vegetarian) {
|
||||
this.vegetarian = vegetarian;
|
||||
}
|
||||
|
||||
@JsonProperty("vegan")
|
||||
public Boolean getVegan() {
|
||||
return vegan;
|
||||
}
|
||||
|
||||
@JsonProperty("vegan")
|
||||
public void setVegan(Boolean vegan) {
|
||||
this.vegan = vegan;
|
||||
}
|
||||
|
||||
@JsonProperty("glutenFree")
|
||||
public Boolean getGlutenFree() {
|
||||
return glutenFree;
|
||||
}
|
||||
|
||||
@JsonProperty("glutenFree")
|
||||
public void setGlutenFree(Boolean glutenFree) {
|
||||
this.glutenFree = glutenFree;
|
||||
}
|
||||
|
||||
@JsonProperty("extendedIngredients")
|
||||
public List<ExtendedIngredient> getExtendedIngredients() {
|
||||
return extendedIngredients;
|
||||
}
|
||||
|
||||
@JsonProperty("extendedIngredients")
|
||||
public void setExtendedIngredients(List<ExtendedIngredient> extendedIngredients) {
|
||||
this.extendedIngredients = extendedIngredients;
|
||||
}
|
||||
|
||||
@JsonProperty("id")
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@JsonProperty("id")
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@JsonProperty("title")
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@JsonProperty("title")
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@JsonProperty("readyInMinutes")
|
||||
public Integer getReadyInMinutes() {
|
||||
return readyInMinutes;
|
||||
}
|
||||
|
||||
@JsonProperty("readyInMinutes")
|
||||
public void setReadyInMinutes(Integer readyInMinutes) {
|
||||
this.readyInMinutes = readyInMinutes;
|
||||
}
|
||||
|
||||
@JsonProperty("servings")
|
||||
public Integer getServings() {
|
||||
return servings;
|
||||
}
|
||||
|
||||
@JsonProperty("servings")
|
||||
public void setServings(Integer servings) {
|
||||
this.servings = servings;
|
||||
}
|
||||
|
||||
@JsonProperty("image")
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
@JsonProperty("image")
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
@JsonProperty("spoonacularSourceUrl")
|
||||
public String getSpoonacularSourceUrl() {
|
||||
return spoonacularSourceUrl;
|
||||
}
|
||||
|
||||
@JsonProperty("spoonacularSourceUrl")
|
||||
public void setSpoonacularSourceUrl(String spoonacularSourceUrl) {
|
||||
this.spoonacularSourceUrl = spoonacularSourceUrl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@SpringBootApplication
|
||||
@SpringBootApplication(scanBasePackages = {"spoonaccular", "whattocook"})
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
package whattocook.Controller;
|
||||
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpEntity;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import whattocook.services.SpoonacularApiService;
|
||||
import whattocook.repositories.ItemRepository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/recipes")
|
||||
public class SpoonacularController {
|
||||
private int nextRecepies=10;
|
||||
private int nextRecepiesForOneRandom=20;
|
||||
@Autowired
|
||||
private ItemRepository itemRepository;
|
||||
@Autowired
|
||||
private SpoonacularApiService service;
|
||||
|
||||
@GetMapping("/forFridge")
|
||||
public HttpEntity<JSONArray> getForFridge() throws IOException, InterruptedException, JSONException {
|
||||
return new HttpEntity<JSONArray>(service.getForIngridients(itemRepository.findAll(), nextRecepies));
|
||||
}
|
||||
|
||||
@GetMapping("/random")
|
||||
public HttpEntity<JSONArray> getRandom() throws IOException, InterruptedException, JSONException {
|
||||
return new HttpEntity<JSONArray>(service.getRandom(new LinkedList<>(), nextRecepies));
|
||||
//when user has food preferences apply instead of linked list.
|
||||
}
|
||||
|
||||
@GetMapping("/oneFridge")
|
||||
public HttpEntity<JSONObject> getOneFridge() throws IOException, InterruptedException, JSONException {
|
||||
return new HttpEntity<JSONObject>(service.getOneForIngridients(itemRepository.findAll(), nextRecepiesForOneRandom));
|
||||
}
|
||||
|
||||
public void setNextRecepies(int nextRecepies) {
|
||||
this.nextRecepies = nextRecepies;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package whattocook.controller;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.rest.webmvc.BasePathAwareController;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import spoonaccular.RecipeSearch;
|
||||
import spoonaccular.models.recipe_by_ingredient.ExtendedRecipeByIngredient;
|
||||
import spoonaccular.models.recipe_information.Recipe;
|
||||
import whattocook.repositories.ItemRepository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@RestController()
|
||||
@BasePathAwareController()
|
||||
public class RecipeSearchController {
|
||||
private final int nextRecipes=10;
|
||||
private final int nextRecipesForOneRandom = 20;
|
||||
|
||||
@Autowired
|
||||
private ItemRepository itemRepository;
|
||||
|
||||
@GetMapping("/recipe/forFridge")
|
||||
public List<ExtendedRecipeByIngredient> getForFridge() throws IOException {
|
||||
return RecipeSearch.getForIngridients(itemRepository.findAll(), nextRecipes);
|
||||
}
|
||||
|
||||
@GetMapping("/recipe/random")
|
||||
public List<Recipe> getRandom() throws IOException, JSONException {
|
||||
return RecipeSearch.getRandom(new LinkedList<>(), nextRecipes);
|
||||
//when user has food preferences apply instead of linked list.
|
||||
}
|
||||
|
||||
@GetMapping("/recipe/oneFridge")
|
||||
public ExtendedRecipeByIngredient getOneFridge() throws IOException {
|
||||
return RecipeSearch.getOneForIngridients(itemRepository.findAll(), nextRecipesForOneRandom);
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package whattocook.implementation;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import whattocook.models.Item;
|
||||
import whattocook.services.SpoonacularApiService;
|
||||
import org.json.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.URI;
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
@Service
|
||||
public class SpoonacularApiServiceImpl implements SpoonacularApiService {
|
||||
private final String KEY = "85cc006d508b447a88e659cd748899db";
|
||||
private final String RANKING = "2";
|
||||
private final boolean IGNOREPANTRY = true;
|
||||
Random rnd=new Random();
|
||||
|
||||
public JSONArray getForIngridients(Iterable<Item> items, int number) throws java.io.IOException, InterruptedException, JSONException {
|
||||
Iterator<Item> itemIterator = items.iterator();
|
||||
if (!itemIterator.hasNext()) {
|
||||
return getRandom(new java.util.LinkedList<String>(), number);
|
||||
} else {
|
||||
String ingridients = itemIterator.next().getName();
|
||||
for (Iterator<Item> it = itemIterator; it.hasNext(); ) {
|
||||
Item curryItem = it.next();
|
||||
|
||||
|
||||
ingridients += "," + curryItem.getName();
|
||||
}
|
||||
java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder()
|
||||
.uri(java.net.URI.create("https://api.spoonacular.com/recipes/findByIngredients?apiKey=" + KEY + "&ingredients=" + ingridients + "&ranking=" + RANKING + "&ignorePantry=" + IGNOREPANTRY + "&number=" + number))
|
||||
.method("GET", java.net.http.HttpRequest.BodyPublishers.noBody())
|
||||
.build();
|
||||
java.net.http.HttpResponse<String> response = java.net.http.HttpClient.newHttpClient().send(request, java.net.http.HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
JSONArray array=new JSONArray(response.body());
|
||||
return array;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getOneForIngridients(Iterable<Item> items, int number) throws IOException, InterruptedException, JSONException {
|
||||
JSONArray array= getForIngridients(items, number);
|
||||
|
||||
|
||||
return array.getJSONObject(rnd.nextInt(20));
|
||||
}
|
||||
|
||||
public JSONArray getRandom(java.util.List<String> tags, int number) throws java.io.IOException, InterruptedException, JSONException {
|
||||
if (tags.isEmpty()) {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create("https://api.spoonacular.com/recipes/random?apiKey=" + KEY + "&number=" + number))
|
||||
.method("GET", HttpRequest.BodyPublishers.noBody())
|
||||
.build();
|
||||
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
JSONArray array=new JSONArray(response.body());
|
||||
return array;
|
||||
|
||||
} else {
|
||||
String tagString = tags.get(0);
|
||||
for (int i = 1; i < tags.size(); i++) {
|
||||
tagString += "," + tags.get(i);
|
||||
}
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create("https://api.spoonacular.com/recipes/random?apiKey=" + KEY + "&number=" + number + "&tags=" + tagString))
|
||||
.method("GET", HttpRequest.BodyPublishers.noBody())
|
||||
.build();
|
||||
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
|
||||
JSONArray array=new JSONArray(response.body());
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package whattocook.services;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import whattocook.models.Item;
|
||||
|
||||
public interface SpoonacularApiService {
|
||||
JSONArray getForIngridients(Iterable<Item> items, int number) throws java.io.IOException, InterruptedException, JSONException;
|
||||
JSONObject getOneForIngridients(Iterable<Item> items, int number) throws java.io.IOException, InterruptedException, JSONException;
|
||||
|
||||
JSONArray getRandom(java.util.List<String> tags, int number) throws java.io.IOException, InterruptedException, JSONException;
|
||||
}
|
||||
@@ -3,10 +3,10 @@ server:
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:h2:mem:whattocook
|
||||
username: sa
|
||||
url:
|
||||
username:
|
||||
password:
|
||||
driverClassName: org.h2.Driver
|
||||
driver-class-name:
|
||||
data:
|
||||
rest:
|
||||
base-path: /api/v1
|
||||
10
build.gradle
10
build.gradle
@@ -29,10 +29,18 @@ dependencies {
|
||||
// https://mvnrepository.com/artifact/com.h2database/h2
|
||||
implementation group: 'com.h2database', name: 'h2', version: '1.3.148'
|
||||
|
||||
//lombok
|
||||
// https://mvnrepository.com/artifact/org.postgresql/postgresql
|
||||
implementation group: 'org.postgresql', name: 'postgresql', version: '42.4.0'
|
||||
|
||||
// okhttp
|
||||
implementation("com.squareup.okhttp3:okhttp:4.10.0")
|
||||
|
||||
// lombok
|
||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||
|
||||
implementation 'io.github.cdimascio:dotenv-java:2.2.4'
|
||||
|
||||
testCompileOnly 'org.projectlombok:lombok:1.18.24'
|
||||
testAnnotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||
|
||||
|
||||
@@ -1,17 +1,41 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<ItemModel/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import ItemModel from "@/components/ItemModel";
|
||||
import LoginPage from "@/components/LoginPage";
|
||||
import Custom404Page from "@/components/Custom404Page";
|
||||
|
||||
const routes = {
|
||||
'/': ItemModel,
|
||||
'/login': LoginPage
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ItemModel
|
||||
data() {
|
||||
return {
|
||||
currentPath: window.location.hash
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentView() {
|
||||
return routes[this.currentPath.slice(1) || '/'] || Custom404Page
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('hashchange', () => {
|
||||
this.currentPath = window.location.hash
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="currentView" />
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
<a>Storage</a>
|
||||
</div>
|
||||
|
||||
<span class="divider"></span>
|
||||
|
||||
<input type="checkbox" class="menu-btn" id="menu-btn">
|
||||
<label for="menu-btn" class="menu-icon">
|
||||
<span class="menu-icon__line"></span>
|
||||
@@ -24,16 +22,7 @@
|
||||
|
||||
<ul class="nav-links">
|
||||
<li class="nav-link">
|
||||
<router-link to="/">Home</router-link>
|
||||
</li>
|
||||
<li class="nav-link">
|
||||
<router-link to="/profile">Profile</router-link>
|
||||
</li>
|
||||
<li class="nav-link">
|
||||
<router-link to="/recipes">Recipes</router-link>
|
||||
</li>
|
||||
<li class="nav-link">
|
||||
<router-link to="/shoppinglist">Shoppinglist</router-link>
|
||||
<a href="/#/login">Sign up</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -44,7 +33,7 @@
|
||||
|
||||
<div class="field-header-box">
|
||||
<div class="inputField-header">
|
||||
<input class="newItemName" id="inputTextField" autofocus autocomplete="off" placeholder=" " v-model="newItem"
|
||||
<input class="newItemName" id="inputTextField" autofocus autocomplete="off" placeholder="Add here..." v-model="newItem"
|
||||
@keyup.enter="addItem"/>
|
||||
<label for="inputTextField" class="formLabel">
|
||||
Add here ...
|
||||
@@ -205,7 +194,7 @@ export default Items
|
||||
body{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color:darkcyan;
|
||||
background-color: #213737;
|
||||
}
|
||||
|
||||
.main {
|
||||
@@ -216,7 +205,7 @@ body{
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 1.25vh;
|
||||
background-color: darkcyan;
|
||||
background-color: #213737;
|
||||
}
|
||||
|
||||
/* navbar-background */
|
||||
@@ -226,7 +215,7 @@ body{
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 3;
|
||||
background: darkcyan;
|
||||
background: #213737;
|
||||
width: 100vw;
|
||||
height: 15vh;
|
||||
}
|
||||
@@ -262,11 +251,11 @@ body{
|
||||
border-radius: 0.4411764705882353vh; // times 2 of border
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
color: black;
|
||||
color: white;
|
||||
outline: none;
|
||||
padding: 0.5vh;// size of font
|
||||
box-shadow: 10px 10px 30px rgba(0, 0, 0, 0.4); // 0.5 size of font and 1.5 size of font
|
||||
background: darkcyan;
|
||||
background: #213737;
|
||||
}
|
||||
|
||||
.newItemName:hover {
|
||||
@@ -546,6 +535,4 @@ body{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
626
frontend/src/components/LoginPage.vue
Normal file
626
frontend/src/components/LoginPage.vue
Normal file
@@ -0,0 +1,626 @@
|
||||
<template>
|
||||
|
||||
<div class="main">
|
||||
|
||||
<div v-if="loading">
|
||||
<h1 class="loading">Loading...</h1>
|
||||
</div>
|
||||
<div v-else>
|
||||
|
||||
<!-- navbar -->
|
||||
|
||||
<header class="navbar-header">
|
||||
<div class="logo">
|
||||
<a>Login</a>
|
||||
</div>
|
||||
|
||||
<input id="menu-btn" class="menu-btn" type="checkbox">
|
||||
<label class="menu-icon" for="menu-btn">
|
||||
<span class="menu-icon__line"></span>
|
||||
</label>
|
||||
|
||||
<ul class="nav-links">
|
||||
<li class="nav-link">
|
||||
<a href="/">Storage</a>
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
|
||||
<div id="user-sign-in" class="user-login">
|
||||
<div class="site-background"/>
|
||||
<div class="form-background">
|
||||
<form>
|
||||
|
||||
<h2>Sign In</h2>
|
||||
<input placeholder="Username" type="text">
|
||||
<input placeholder="Password" type="password">
|
||||
<input class="login-btn-apple" type="submit" value="Login Apple">
|
||||
<input class="login-btn" type="submit" value="Login">
|
||||
<p class="signup">Don't have an account?
|
||||
<a href="#/login" v-on:click="isSignUp = !isSignUp">Sign up</a>
|
||||
</p>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :style="{'display': isSignUp ? 'none' : ''}" class="user-signup">
|
||||
<div class="site-background"/>
|
||||
<div class="form-background">
|
||||
<form>
|
||||
|
||||
<h2>Create Account</h2>
|
||||
<input placeholder="Username" type="text">
|
||||
<input placeholder="Email Address" type="text">
|
||||
<input placeholder="Create Password" type="password">
|
||||
<input placeholder="Confirm Password" type="password">
|
||||
<input type="submit" value="Sign Up" class="submit">
|
||||
<p class="signup">Have an account?
|
||||
<br>
|
||||
<a href="#/login" v-on:click="isSignUp = !isSignUp">Sign in</a>
|
||||
</p>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet"
|
||||
type='text/css'/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "LoginPage",
|
||||
data() {
|
||||
return {
|
||||
isSignUp: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200&display=swap');
|
||||
@import 'src/styling/navbar';
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.main {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
height: 100vh;
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #213737;
|
||||
}
|
||||
|
||||
.logo {
|
||||
left: -3vh;
|
||||
top: 1vh;
|
||||
}
|
||||
|
||||
.logo a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
left: 3vh;
|
||||
top: 1vh;
|
||||
|
||||
&__line, &__line:before, &__line::after {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
/* login / signin styling */
|
||||
|
||||
section {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40px;
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
width: 2800px;
|
||||
height: 1700px;
|
||||
background: white;
|
||||
box-shadow: 0 15px 50px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.user-login {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
||||
.site-background {
|
||||
position: relative;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
transition: 0.5s;
|
||||
//background: url('../ressouce/5008bf96009ea69ba157815061bce4f2.png');
|
||||
background: brown;
|
||||
}
|
||||
|
||||
.form-background {
|
||||
position: relative;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 160px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
position: relative;
|
||||
font-size: 60px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 8px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
color: black;
|
||||
top: -30px;
|
||||
}
|
||||
|
||||
h2:after {
|
||||
content: '';
|
||||
display: block;
|
||||
border-bottom: 4px solid #000;
|
||||
height: 0;
|
||||
position: relative;
|
||||
top: 50px;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 40px;
|
||||
background: lightgrey;
|
||||
border: none;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
font-size: 1vh;
|
||||
letter-spacing: 4px;
|
||||
margin: 20px 0;
|
||||
top: 50px;
|
||||
color: black;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
cursor: pointer;
|
||||
max-width: 520px;
|
||||
transition: 0.5s;
|
||||
background-color: darkslategrey;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
position: relative;
|
||||
left: 40px;
|
||||
box-shadow: 10px 10px 30px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.login-btn-apple {
|
||||
box-shadow: 10px 10px 30px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.login-btn:hover, .login-btn-apple:hover {
|
||||
background: brown;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.signup {
|
||||
text-align: center;
|
||||
justify-content: right;
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin-top: 550px;
|
||||
top: 50px;
|
||||
font-size: 40px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 4px;
|
||||
//border: 1px solid black;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
color: darkslategrey;
|
||||
letter-spacing: 2px;
|
||||
font-size: 50px;
|
||||
transition: color 0.5s ease-in-out;
|
||||
//border: 1px solid black;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
left: 30%;
|
||||
top: -8px;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
color: brown;
|
||||
}
|
||||
}
|
||||
|
||||
.user-signup {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: display 0.5s ease-in-out;
|
||||
|
||||
.site-background {
|
||||
position: relative;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
left: 50%;
|
||||
transition: 0.5s;
|
||||
//background: url('../ressouce/5008bf96009ea69ba157815061bce4f2.png');
|
||||
background: brown;
|
||||
}
|
||||
|
||||
.form-background {
|
||||
position: relative;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 160px;
|
||||
top: -100%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
position: relative;
|
||||
font-size: 60px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 8px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
color: black;
|
||||
top: 150px;
|
||||
}
|
||||
|
||||
h2:after {
|
||||
content: '';
|
||||
display: block;
|
||||
border-bottom: 4px solid #000;
|
||||
height: 0;
|
||||
position: relative;
|
||||
top: 50px;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 40px;
|
||||
background: lightgrey;
|
||||
border: none;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
font-size: 40px;
|
||||
letter-spacing: 4px;
|
||||
margin: 20px 0;
|
||||
top: 230px;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.submit{
|
||||
box-shadow: 10px 10px 30px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.submit:hover{
|
||||
background: brown;
|
||||
color: black;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
cursor: pointer;
|
||||
max-width: 520px;
|
||||
transition: 0.5s;
|
||||
background-color: darkslategrey;
|
||||
color: white;
|
||||
left: 51.8%;
|
||||
}
|
||||
|
||||
.signup {
|
||||
text-align: center;
|
||||
justify-content: left;
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin-top: 560px;
|
||||
font-size: 20px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 4px;
|
||||
top: -130px;
|
||||
//border: 1px solid black;
|
||||
}
|
||||
|
||||
a {
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
color: darkslategrey;
|
||||
letter-spacing: 2px;
|
||||
font-size: 50px;
|
||||
top: -10px;
|
||||
left: 30%;
|
||||
transition: color 0.5s ease-in-out;
|
||||
//border: 1px solid black;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
color: brown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-device-height: 1440px) {
|
||||
|
||||
/* login / signin styling */
|
||||
|
||||
section {
|
||||
padding: 52px;
|
||||
|
||||
.container {
|
||||
width: 1800px;
|
||||
height: 1200px;
|
||||
box-shadow: 0 15px 50px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.user-login {
|
||||
|
||||
.form-background {
|
||||
padding: 106px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 40px;
|
||||
letter-spacing: 6px;
|
||||
margin-bottom: 14px;
|
||||
top: -40px;
|
||||
}
|
||||
|
||||
h2:after {
|
||||
border-bottom: 4px solid #000;
|
||||
top: 26px;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 26px;
|
||||
letter-spacing: 4px;
|
||||
margin: 14px 0;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
max-width: 330px;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
left: 28px;
|
||||
}
|
||||
|
||||
.signup {
|
||||
margin-top: 400px;
|
||||
letter-spacing: 2px;
|
||||
font-size: 20px;
|
||||
top: 20px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
a {
|
||||
letter-spacing: 4px;
|
||||
font-size: 40px;
|
||||
top: 50px;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.user-signup {
|
||||
|
||||
.form-background {
|
||||
padding: 106px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 40px;
|
||||
letter-spacing: 6px;
|
||||
margin-bottom: 140px;
|
||||
top: 120px;
|
||||
}
|
||||
|
||||
h2:after {
|
||||
border-bottom: 4px solid #000;
|
||||
top: 26px;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 26px;
|
||||
font-size: 26px;
|
||||
letter-spacing: 4px;
|
||||
margin: 14px 0;
|
||||
top: 27px;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
max-width: 330px;
|
||||
left: 52%;
|
||||
}
|
||||
|
||||
.signup {
|
||||
margin-top: 374px;
|
||||
letter-spacing: 2px;
|
||||
top: -154px;
|
||||
font-size: 20px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
a {
|
||||
letter-spacing: 4px;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
font-size: 40px;
|
||||
top: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-device-height: 1080px) {
|
||||
|
||||
/* login / signin styling */
|
||||
|
||||
section {
|
||||
padding: 40px;
|
||||
|
||||
.container {
|
||||
width: 1500px;
|
||||
height: 900px;
|
||||
box-shadow: 0 7.5px 25px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.user-login {
|
||||
|
||||
.form-background {
|
||||
padding: 80px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 30px;
|
||||
letter-spacing: 4px;
|
||||
margin-bottom: 10px;
|
||||
top: -25px;
|
||||
}
|
||||
|
||||
h2:after {
|
||||
border-bottom: 2px solid #000;
|
||||
top: 25px;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 12px;
|
||||
font-size: 12px;
|
||||
letter-spacing: 2px;
|
||||
margin: 10px 0;
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
max-width: 285px;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.signup {
|
||||
position: relative;
|
||||
margin-top: 300px;
|
||||
letter-spacing: 2px;
|
||||
font-size: 0.05vh;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
a {
|
||||
letter-spacing: 1px;
|
||||
align-content: center;
|
||||
font-size: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-signup {
|
||||
|
||||
.form-background {
|
||||
padding: 80px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 30px;
|
||||
letter-spacing: 4px;
|
||||
margin-bottom: 10px;
|
||||
top: 50px;
|
||||
}
|
||||
|
||||
h2:after {
|
||||
border-bottom: 2px solid #000;
|
||||
top: 25px;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 12px;
|
||||
font-size: 12px;
|
||||
letter-spacing: 2px;
|
||||
margin: 10px 0;
|
||||
top: 90px;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
max-width: 260px;
|
||||
left: 55.8%;
|
||||
}
|
||||
|
||||
.signup {
|
||||
margin-top: 280px;
|
||||
letter-spacing: 2px;
|
||||
top: -60px;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
a {
|
||||
letter-spacing: 2px;
|
||||
font-size: 40px;
|
||||
align-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -18,8 +18,6 @@
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
|
||||
a {
|
||||
margin: 0.2vh;
|
||||
@@ -30,18 +28,11 @@
|
||||
a:hover {
|
||||
font-size: 3vh;
|
||||
transition: all 300ms;
|
||||
color: brown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.divider{
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
border-bottom: 0.1vh solid black;
|
||||
margin: 5px;
|
||||
top: 2vh;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
position: relative;
|
||||
padding: 0.5vh 0.5vh;
|
||||
@@ -122,8 +113,9 @@
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
padding: 5vh 0;
|
||||
width: 100vw;
|
||||
height: 120vh;
|
||||
@@ -131,9 +123,8 @@
|
||||
letter-spacing: 0.25vh;
|
||||
color: white;
|
||||
background: #272727;
|
||||
|
||||
transition: opacity 0.8s 0.5s,
|
||||
clip-path 1s 0.5s;
|
||||
align-content: center;
|
||||
transition: opacity 0.8s 0.5s, clip-path 1s 0.5s;
|
||||
clip-path: circle(9.615384615384615vh at top right);
|
||||
|
||||
.nav-links {
|
||||
@@ -141,6 +132,8 @@
|
||||
transform: translateX(100%);
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
@@ -160,9 +153,21 @@
|
||||
clip-path: circle(100% at center);
|
||||
|
||||
.nav-link {
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
display: flex;
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
a {
|
||||
position: relative;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
right: -0.2vh;
|
||||
top: -11.5vh;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-btn:checked ~ .menu-icon {
|
||||
@@ -183,6 +188,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logo{
|
||||
a {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
font-size: 4vh;
|
||||
top: -0.68vh;
|
||||
}
|
||||
a:hover{
|
||||
font-size: 4vh;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes openButtonBefore {
|
||||
|
||||
Reference in New Issue
Block a user