diff --git a/api/src/public/api.json b/api/src/public/api.json index e5ab6ef..97de5a0 100644 --- a/api/src/public/api.json +++ b/api/src/public/api.json @@ -1 +1 @@ -{"version":"2.0.0","endpoints":{"user":{"signup":{"name":"user","operation":"signup","route":"/api/v1/auth/signup","method":"POST","description":"user signup api","body":{"username":"testuser","email":"text@example.com","password":"Test1234"},"response":"status object"},"signin":{"name":"user","operation":"signin","route":"/api/v1/auth/signin","method":"POST","description":"user signin api","body":{"email":"text@example.com","password":"Test1234"},"response":"status object"},"logout":{"name":"user","operation":"logout","route":"/api/v1/auth/logout","method":"POST","description":"user logout api","body":{},"response":"status object"},"status":{"name":"user","operation":"status","route":"/api/v1/auth/status","method":"GET","description":"user login status api","response":"status code | user object"}},"beer":{"add":{"name":"beer","operation":"add","route":"/api/v1/beer/add","method":"POST","description":"beer add api","body":{"brand":"Pilsner Urqell","name":"Kozel","degree":11,"packaging":"can","photos":"optional field | max 4 images | formData"},"response":"status object | beer object"},"get":{"name":"beer","operation":"get","route":"/api/v1/beer/get","method":"GET","description":"beer get api","response":"status object | array of beer objects"},"del":{"name":"beer","operation":"del","route":"/api/v1/beer/del","method":"POST","description":"beer del api","body":{"_id":"6352b303b71cb62222f39895"},"response":"status object"},"edit":{"name":"beer","operation":"edit","route":"/api/v1/beer/edit","method":"POST","description":"beer edit api","body":{"_id":"6355b95dc03fad77bc380146","brand":"Pilsner Urqell","name":"Radegast","degree":12,"packaging":"bottle","imgs":[],"photos":"optional field | max 4 images | formData"},"response":"status object | beer data"}},"docs":{"get_all":{"name":"docs","operation":"get_all","route":"/api/v1","method":"GET","description":"Get docs json","response":"docs json"}}}} \ No newline at end of file +{"version":"2.0.0","endpoints":{"user":{"signup":{"name":"user","operation":"signup","route":"/api/v1/auth/signup","method":"POST","description":"user signup api","body":{"username":"testuser","email":"text@example.com","password":"Test1234"},"response":"status object"},"signin":{"name":"user","operation":"signin","route":"/api/v1/auth/signin","method":"POST","description":"user signin api","body":{"email":"text@example.com","password":"Test1234"},"response":"status object"},"logout":{"name":"user","operation":"logout","route":"/api/v1/auth/logout","method":"POST","description":"user logout api","body":{},"response":"status object"},"status":{"name":"user","operation":"status","route":"/api/v1/auth/status","method":"GET","description":"user login status api","response":"status code | user object"}},"beer":{"add":{"name":"beer","operation":"add","route":"/api/v1/beer/add","method":"POST","description":"beer add api","body":{"brand":"Pilsner Urqell","name":"Kozel","degree":11,"packaging":"can","photos":"optional field | max 4 images | formData"},"response":"status object | beer object"},"get":{"name":"beer","operation":"get","route":"/api/v1/beer/get","method":"GET","description":"beer get api","response":"status object | array of beer objects"},"del":{"name":"beer","operation":"del","route":"/api/v1/beer/del","method":"POST","description":"beer del api","body":{"_id":"6352b303b71cb62222f39895"},"response":"status object"},"edit":{"name":"beer","operation":"edit","route":"/api/v1/beer/edit","method":"POST","description":"beer edit api","body":{"_id":"6355b95dc03fad77bc380146","brand":"Pilsner Urqell","name":"Radegast","degree":12,"packaging":"bottle","imgs":[],"photos":"optional field | max 4 images | formData"},"response":"status object | beer data"}},"docs":{"get_all":{"name":"docs","operation":"get_all","route":"/api/v1","method":"GET","description":"Get docs json","response":"docs json"}},"review":{"add":{"name":"review","operation":"add","route":"/api/v1/review/add","method":"POST","description":"review add api","body":{"beer_id":"6352b303b71cb62222f39895","foam":3,"bitter_sweetness":2,"taste":5,"packaging":3,"sourness":false,"would_again":true},"response":"status object | review object"},"get":{"name":"review","operation":"get","route":"/api/v1/review/get","method":"GET","description":"review get api","response":"status object | array of review objects"},"del":{"name":"review","operation":"del","route":"/api/v1/review/del","method":"POST","description":"review del api","body":{"_id":"6352b303b71cb62222f39895"},"response":"status object"}}}} \ No newline at end of file diff --git a/frontend/app/(app)/(tabs)/_layout.js b/frontend/app/(app)/(tabs)/_layout.js index be70c82..8b8d7d7 100644 --- a/frontend/app/(app)/(tabs)/_layout.js +++ b/frontend/app/(app)/(tabs)/_layout.js @@ -43,7 +43,7 @@ export default function TabLayout() { }} /> ( @@ -66,6 +66,10 @@ export default function TabLayout() { name="beer/add" options={{ href: null, title: "Add beer" }} /> + ); diff --git a/frontend/app/(app)/(tabs)/review.js b/frontend/app/(app)/(tabs)/review.js deleted file mode 100644 index 0b22c72..0000000 --- a/frontend/app/(app)/(tabs)/review.js +++ /dev/null @@ -1,10 +0,0 @@ -import { View } from "react-native"; -import Text from "@components/Text"; - -export default function Tab() { - return ( - - Tab REVIEW - - ); -} diff --git a/frontend/app/(app)/(tabs)/review/.index.js.swp b/frontend/app/(app)/(tabs)/review/.index.js.swp new file mode 100644 index 0000000..b42827b Binary files /dev/null and b/frontend/app/(app)/(tabs)/review/.index.js.swp differ diff --git a/frontend/app/(app)/(tabs)/review/add.js b/frontend/app/(app)/(tabs)/review/add.js new file mode 100644 index 0000000..f12643f --- /dev/null +++ b/frontend/app/(app)/(tabs)/review/add.js @@ -0,0 +1,233 @@ +import { StyleSheet, TextInput, View, Image } from "react-native"; +import { useState } from "react"; +import Button from "@components/Button"; +import Text from "@components/Text"; +import { colors } from "@components/style"; +import * as ImagePicker from "expo-image-picker"; +import DropDownPicker from "react-native-dropdown-picker"; +const DropdownTheme = require("@components/DropdownTheme"); +import { Platform } from "react-native"; +import RangeSlider, { Slider } from "react-native-range-slider-expo"; + +export default function reviewAdd() { + const [b_name, setBName] = useState(""); + const [b_degree, setBDegree] = useState(""); + const [b_packaging, setBPackaging] = useState(null); + const [b_brand, setBBrand] = useState(""); + const [image, setImage] = useState(null); + + const [open, setOpen] = useState(false); + const [items, setItems] = useState([ + { label: "Tank beer", value: "tank" }, + { label: "Cask beer", value: "cask" }, + { label: "Glass bottle", value: "glass" }, + { label: "Can", value: "can" }, + { label: "PET bottle", value: "pet" }, + ]); + + DropDownPicker.addTheme("DropdownTheme", DropdownTheme); + DropDownPicker.setTheme("DropdownTheme"); + + ImagePicker.getCameraPermissionsAsync(); //check if the user has granted permission to access the camera + const pickImage = async () => { + const permissionResult = + await ImagePicker.requestMediaLibraryPermissionsAsync(); + + if (permissionResult.granted === false) { + alert("You've refused to allow this appp to access your photos!"); + return; + } + + // No permissions request is necessary for launching the image library + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + allowsEditing: true, + aspect: [3, 4], + // quality: 1, + }); + + // Explore the result + console.log(result); + + if (!result.canceled) { + setImage(result.assets[0].uri); + } + }; + + const openCamera = async () => { + // Ask the user for the permission to access the camera + const permissionResult = await ImagePicker.requestCameraPermissionsAsync(); + + if (permissionResult.granted === false) { + alert("You've refused to allow this app to access your camera!"); + return; + } + + const result = await ImagePicker.launchCameraAsync(); + + // Explore the result + console.log(result); + + if (!result.canceled) { + setImage(result.assets[0].uri); + } + }; + + function validateDegreeInput(text) { + let newText = ""; + let numbers = "0123456789."; + + for (var i = 0; i < text.length; i++) { + if (numbers.indexOf(text[i]) > -1) { + newText = newText + text[i]; + setBDegree(newText); + } else { + // your call back function + alert("Please enter numbers only."); + setBDegree(""); + } + } + } + + async function addBeer() { + // TODO: after the request - redirect to /beer/{new_beer_id}?; plus some modal about successful state + const req = await fetch(`${process.env.EXPO_PUBLIC_API_URL}/beer/add`, { + method: "POST", + credentials: "include", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + brand: b_brand, + name: b_name, + degree: b_degree, + packaging: b_packaging, + photos: null, + }), + }); + const res = await req.json(); + + if (res.code == 201 && res.data._id) { + window.location.href = `/beer/${res.data._id}`; + } else { + alert( + "Beer was not added successfully. Please check your data and try again.", + ); + } + } + + return ( + + + + Spill your thoughts about the beer you just sipped! + + setBName(text)} + placeholderTextColor="#aaaaaa" + /> + setBBrand(text)} + placeholderTextColor="#aaaaaa" + /> + validateDegreeInput(text)} + placeholderTextColor="#aaaaaa" + keyboardType="numeric" + maxLength={3} + /> + + + {/* +