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
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
frontend/src/index.js
|
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;
|
import java.util.Collections;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication(scanBasePackages = {"spoonaccular", "whattocook"})
|
||||||
public class Application {
|
public class Application {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
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:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:h2:mem:whattocook
|
url:
|
||||||
username: sa
|
username:
|
||||||
password:
|
password:
|
||||||
driverClassName: org.h2.Driver
|
driver-class-name:
|
||||||
data:
|
data:
|
||||||
rest:
|
rest:
|
||||||
base-path: /api/v1
|
base-path: /api/v1
|
||||||
10
build.gradle
10
build.gradle
@@ -29,10 +29,18 @@ dependencies {
|
|||||||
// https://mvnrepository.com/artifact/com.h2database/h2
|
// https://mvnrepository.com/artifact/com.h2database/h2
|
||||||
implementation group: 'com.h2database', name: 'h2', version: '1.3.148'
|
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'
|
compileOnly 'org.projectlombok:lombok:1.18.24'
|
||||||
annotationProcessor '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'
|
testCompileOnly 'org.projectlombok:lombok:1.18.24'
|
||||||
testAnnotationProcessor '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>
|
<script>
|
||||||
import ItemModel from "@/components/ItemModel";
|
import ItemModel from "@/components/ItemModel";
|
||||||
|
import LoginPage from "@/components/LoginPage";
|
||||||
|
import Custom404Page from "@/components/Custom404Page";
|
||||||
|
|
||||||
|
const routes = {
|
||||||
|
'/': ItemModel,
|
||||||
|
'/login': LoginPage
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
data() {
|
||||||
ItemModel
|
return {
|
||||||
|
currentPath: window.location.hash
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentView() {
|
||||||
|
return routes[this.currentPath.slice(1) || '/'] || Custom404Page
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
window.addEventListener('hashchange', () => {
|
||||||
|
this.currentPath = window.location.hash
|
||||||
|
})
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<component :is="currentView" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
[v-cloak] {
|
[v-cloak] {
|
||||||
display: none;
|
display: none;
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
<a>Storage</a>
|
<a>Storage</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="divider"></span>
|
|
||||||
|
|
||||||
<input type="checkbox" class="menu-btn" id="menu-btn">
|
<input type="checkbox" class="menu-btn" id="menu-btn">
|
||||||
<label for="menu-btn" class="menu-icon">
|
<label for="menu-btn" class="menu-icon">
|
||||||
<span class="menu-icon__line"></span>
|
<span class="menu-icon__line"></span>
|
||||||
@@ -24,16 +22,7 @@
|
|||||||
|
|
||||||
<ul class="nav-links">
|
<ul class="nav-links">
|
||||||
<li class="nav-link">
|
<li class="nav-link">
|
||||||
<router-link to="/">Home</router-link>
|
<a href="/#/login">Sign up</a>
|
||||||
</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>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,7 +33,7 @@
|
|||||||
|
|
||||||
<div class="field-header-box">
|
<div class="field-header-box">
|
||||||
<div class="inputField-header">
|
<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"/>
|
@keyup.enter="addItem"/>
|
||||||
<label for="inputTextField" class="formLabel">
|
<label for="inputTextField" class="formLabel">
|
||||||
Add here ...
|
Add here ...
|
||||||
@@ -205,7 +194,7 @@ export default Items
|
|||||||
body{
|
body{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color:darkcyan;
|
background-color: #213737;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
@@ -216,7 +205,7 @@ body{
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 1.25vh;
|
font-size: 1.25vh;
|
||||||
background-color: darkcyan;
|
background-color: #213737;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* navbar-background */
|
/* navbar-background */
|
||||||
@@ -226,7 +215,7 @@ body{
|
|||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
background: darkcyan;
|
background: #213737;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 15vh;
|
height: 15vh;
|
||||||
}
|
}
|
||||||
@@ -262,11 +251,11 @@ body{
|
|||||||
border-radius: 0.4411764705882353vh; // times 2 of border
|
border-radius: 0.4411764705882353vh; // times 2 of border
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
color: black;
|
color: white;
|
||||||
outline: none;
|
outline: none;
|
||||||
padding: 0.5vh;// size of font
|
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
|
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 {
|
.newItemName:hover {
|
||||||
@@ -546,6 +535,4 @@ body{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</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 {
|
.nav-links {
|
||||||
display: flex;
|
|
||||||
list-style: none;
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
margin: 0.2vh;
|
margin: 0.2vh;
|
||||||
@@ -30,18 +28,11 @@
|
|||||||
a:hover {
|
a:hover {
|
||||||
font-size: 3vh;
|
font-size: 3vh;
|
||||||
transition: all 300ms;
|
transition: all 300ms;
|
||||||
|
color: brown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider{
|
|
||||||
position: relative;
|
|
||||||
flex-grow: 1;
|
|
||||||
border-bottom: 0.1vh solid black;
|
|
||||||
margin: 5px;
|
|
||||||
top: 2vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-icon {
|
.menu-icon {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0.5vh 0.5vh;
|
padding: 0.5vh 0.5vh;
|
||||||
@@ -122,8 +113,9 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-evenly;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
padding: 5vh 0;
|
padding: 5vh 0;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 120vh;
|
height: 120vh;
|
||||||
@@ -131,9 +123,8 @@
|
|||||||
letter-spacing: 0.25vh;
|
letter-spacing: 0.25vh;
|
||||||
color: white;
|
color: white;
|
||||||
background: #272727;
|
background: #272727;
|
||||||
|
align-content: center;
|
||||||
transition: opacity 0.8s 0.5s,
|
transition: opacity 0.8s 0.5s, clip-path 1s 0.5s;
|
||||||
clip-path 1s 0.5s;
|
|
||||||
clip-path: circle(9.615384615384615vh at top right);
|
clip-path: circle(9.615384615384615vh at top right);
|
||||||
|
|
||||||
.nav-links {
|
.nav-links {
|
||||||
@@ -141,6 +132,8 @@
|
|||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
display: grid;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -160,9 +153,21 @@
|
|||||||
clip-path: circle(100% at center);
|
clip-path: circle(100% at center);
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
display: flex;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0);
|
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 {
|
.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 {
|
@keyframes openButtonBefore {
|
||||||
|
|||||||
Reference in New Issue
Block a user