Skip to content

Commit

Permalink
Merge branch 'feature/us5-recipe-details' of https://github.com/UB-ES…
Browse files Browse the repository at this point in the history
…-2023-A2/kasula-frontend into feature/us8-rate-review-recipes
  • Loading branch information
ivanmansilla committed Dec 13, 2023
2 parents f315c52 + aec4448 commit 5a6cf64
Show file tree
Hide file tree
Showing 13 changed files with 660 additions and 26 deletions.
28 changes: 28 additions & 0 deletions src/assets/jsonData/sort_options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{"fields": [{
"name": "none",
"displayName": "---"
}, {
"name": "name",
"displayName": "Title"
}, {
"name": "average_rating",
"displayName": "Rating"
}, {
"name": "cooking_time",
"displayName": "Cooking Time"
}, {
"name": "difficulty",
"displayName": "Difficulty"
}, {
"name": "energy",
"displayName": "Energy"
}, {
"name": "username",
"displayName": "Recipe Author"
}, {
"name": "creation_date",
"displayName": "Creation Date"
}, {
"name": "updated_at",
"displayName": "Last Modified"
}]}
7 changes: 7 additions & 0 deletions src/components/KasulaNavbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ function KasulaNavbar() {
<Dropdown.Menu className="dropdown-menu-end">
<Dropdown.Item
eventKey={1}
href={`/UserProfile/${user._id}`}
>
Profile
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item
eventKey={2}
onClick={() => {
handleOpenModal();
}}
Expand Down
8 changes: 4 additions & 4 deletions src/components/ModifyReview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ const ModifyReview = ({ show, reviewId, recipeId, onHide, reloadReviews, funct,

return (
<Modal show={show} onHide={onHide}>
<Modal.Header closeButton className="fw-bold" style={{ backgroundColor: "#ffb79fe0"}}>
<Modal.Header closeButton className="fw-bold bg-normal">
<Modal.Title>{funct === 'Edit' ? 'Modify' : 'Delete'} review</Modal.Title>
</Modal.Header>
<Modal.Body style={{ backgroundColor: "#ffb79fe0"}}>
<Modal.Body className="bg-lightest">
{funct === 'Edit' ? (
<Form>
<Form.Group className="mb-3 fw-bold">
Expand All @@ -132,14 +132,14 @@ const ModifyReview = ({ show, reviewId, recipeId, onHide, reloadReviews, funct,
</Form.Group>
<Form.Group className="mb-3 fw-bold">
<Form.Label>New Rating</Form.Label>
<div className='bg-white pb-1'>{renderStars(newRating)}</div>
<div>{renderStars(newRating)}</div>
</Form.Group>
</Form>
) : (
<p className='fw-bold fs-4'>Are you sure delete review?</p>
)}
</Modal.Body>
<Modal.Footer style={{ backgroundColor: "#ffb79fe0"}}>
<Modal.Footer style={{ backgroundColor: "#ffe7dfe0"}}>
{funct === 'Edit' ? (
<Button className='bg-danger fw-bold border-secondary text-white' variant="primary" onClick={handleUpdateReview} disabled={characterCount > 120}>
Update
Expand Down
8 changes: 4 additions & 4 deletions src/components/PostReview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ const PostReview = ({ id, show, onHide, reloadReviews }) => {

return (<>
<Modal show={show} onHide={onHide}>
<Modal.Header closeButton className="fw-bold" style={{ backgroundColor: "#ffb79fe0" }}>
<Modal.Header closeButton className="fw-bold bg-normal">
<Modal.Title>Post a review</Modal.Title>
</Modal.Header>
<Modal.Body style={{ backgroundColor: "#ffb79fe0" }}>
<Modal.Body className="bg-lightest">
<Form>
<Form.Group className="mb-3 fw-bold">
<Form.Label>Review</Form.Label>
Expand All @@ -133,7 +133,7 @@ const PostReview = ({ id, show, onHide, reloadReviews }) => {
</Form.Group>
<Form.Group className="mb-3 fw-bold">
<Form.Label>Rating</Form.Label>
<div className='bg-white pb-1'>{renderStars(difficulty)}</div>
<div>{renderStars(difficulty)}</div>
</Form.Group>

<Form.Group className="mb-3 fw-bold">
Expand All @@ -142,7 +142,7 @@ const PostReview = ({ id, show, onHide, reloadReviews }) => {
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer style={{ backgroundColor: "#ffb79fe0"}}>
<Modal.Footer style={{ backgroundColor: "#ffe7dfe0"}}>
<Button variant="secondary" onClick={onHide}>
Close
</Button>
Expand Down
222 changes: 222 additions & 0 deletions src/components/RecipeBrowser.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import { useState } from "react";
import {
Container,
Stack,
InputGroup,
Form,
Offcanvas,
Badge,
} from "react-bootstrap";
import { Funnel, FunnelFill, X, SortUp, SortDown } from "react-bootstrap-icons";

import RecipeFilters from "./RecipeFilters";
import sort_options from "../assets/jsonData/sort_options.json";
import "../css/common.css";

function RecipeBrowser({ onSearch }) {
const keyParsing = {
sortBy: "Sort by:",
sortAscending: "",
maxDifficulty: "Difficulty:",
maxTime: "Time:",
minRating: "Rating:",
maxCalories: "Calories",
};

const valueParsing = {
sortBy: "",
sortAscending: "",
maxDifficulty: " stars or less",
maxTime: " min or less",
minRating: " stars or more",
maxCalories: " cal or less",
};

const defaultFilters = {
sortBy: "none",
sortAscending: false,
maxDifficulty: 5,
maxTime: 180,
minRating: 0,
maxCalories: 5000,
};

const [recipeName, setRecipeName] = useState("");
const [filtersOffCanvas, setFiltersOffCanvas] = useState({
title: "Filters",
show: false,
values: JSON.parse(localStorage.getItem("filters")) || defaultFilters,
});

const handleCloseOffcanvas = (
setOffCanvasState,
offCanvasState,
applyFilters,
filterValues
) => {
setOffCanvasState({
...offCanvasState,
show: false,
values: filterValues || offCanvasState.values,
});
if (applyFilters) {
onSearch(filterValues || offCanvasState.values, recipeName);
}
};

return (
<Container>
<Container className="d-flex">
<span
className="fs-3 ms-auto me-3 colorless-span-button position"
role="button"
onClick={() => {
setFiltersOffCanvas({ ...filtersOffCanvas, show: true });
}}
>
<FunnelFill />
</span>
<InputGroup id="search-bar-container" className="w-25">
<Form.Control
className="d-flex shadow-none"
id="search-bar"
type="text"
placeholder="Search..."
value={recipeName}
onChange={(e) => {
setRecipeName(e.target.value);
onSearch(filtersOffCanvas.values, e.target.value);
}}
/>
<InputGroup.Text className="fs-4" id="search-bar-clear">
{recipeName.length > 0 && (
<X
className="colorless-span-button"
role="button"
onClick={() => {
setRecipeName("");
onSearch(filtersOffCanvas.values, "");
}}
/>
)}
</InputGroup.Text>
</InputGroup>
</Container>
<Container className="d-flex mt-4">
{JSON.stringify(filtersOffCanvas.values) !==
JSON.stringify(defaultFilters) && (
<div
className="d-flex colorless-span-button me-4"
role="button"
onClick={() => {
setFiltersOffCanvas({
...filtersOffCanvas,
values: defaultFilters,
});
localStorage.setItem("filters", JSON.stringify(defaultFilters));
onSearch(defaultFilters, recipeName);
}}
>
<X className="fs-5 mt-1" />
<span className="mx-2">Clear filters</span>
<Funnel className="fs-5 mt-1" />
</div>
)}
<Stack direction="horizontal" gap={2}>
{Object.entries(filtersOffCanvas.values)
.filter(
([key, value]) =>
value !== defaultFilters[key] ||
(key === "sortAscending" &&
filtersOffCanvas.values.sortBy !== "none")
)
.map(([key, value]) => (
<Badge pill bg="secondary">
{keyParsing[key]}{" "}
{key === "sortBy"
? sort_options.fields.filter(
(option) => option.name === value
)[0].displayName
: value === true
? "Ascending"
: value === false
? "Descending"
: value.toString().concat(valueParsing[key])}
{key === "sortAscending" ? (
<div
className="ms-1 d-inline-block"
role="button"
onClick={() => {
const newValues = { ...filtersOffCanvas.values };
newValues[key] = !newValues[key];
setFiltersOffCanvas({
...filtersOffCanvas,
values: newValues,
});
localStorage.setItem(
"filters",
JSON.stringify(newValues)
);
onSearch(newValues, recipeName);
}}
>
{value ? (
<SortUp />
) : (
<SortDown className="ms-1" role="button" />
)}
</div>
) : (
<X
className="ms-1"
role="button"
onClick={() => {
const newValues = { ...filtersOffCanvas.values };
newValues[key] = defaultFilters[key];
setFiltersOffCanvas({
...filtersOffCanvas,
values: newValues,
});
localStorage.setItem(
"filters",
JSON.stringify(newValues)
);
onSearch(newValues, recipeName);
}}
/>
)}
</Badge>
))}
</Stack>
</Container>
<Offcanvas
show={filtersOffCanvas.show}
onHide={() =>
handleCloseOffcanvas(setFiltersOffCanvas, filtersOffCanvas, false)
}
>
<Offcanvas.Header closeButton className="bg-normal">
<Offcanvas.Title className="fs-3 fw-semi-bold">
{filtersOffCanvas.title}
</Offcanvas.Title>
</Offcanvas.Header>
<Offcanvas.Body className="p-0">
<RecipeFilters
onClose={(filters) => {
localStorage.setItem("filters", JSON.stringify(filters));
handleCloseOffcanvas(
setFiltersOffCanvas,
filtersOffCanvas,
true,
filters
);
}}
inValues={filtersOffCanvas.values}
/>
</Offcanvas.Body>
</Offcanvas>
</Container>
);
}

export default RecipeBrowser;
Loading

0 comments on commit 5a6cf64

Please sign in to comment.