Skip to content

Commit

Permalink
Merge pull request #244 from bounswe/frontend/feature/151-recipe-page
Browse files Browse the repository at this point in the history
Frontend/feature/151 recipe page
  • Loading branch information
mmtftr authored May 15, 2024
2 parents 2f4f9a2 + 242b12e commit eab4b9e
Show file tree
Hide file tree
Showing 19 changed files with 597 additions and 99 deletions.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"dependencies": {
"@hookform/error-message": "^2.0.1",
"@hookform/resolvers": "^3.3.4",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-aspect-ratio": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/assets/Icon/General/Bookmark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion frontend/src/assets/Icon/General/Filter.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions frontend/src/assets/Icon/General/Link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions frontend/src/components/ErrorAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { AlertCircle } from "lucide-react";
import { Alert, AlertDescription, AlertTitle } from "./ui/alert";
import { renderError } from "@/services/api/semanticBrowseFetcher";

export default function ErrorAlert<
T extends Parameters<typeof renderError>[0],
>({ error }: { error: T }) {
return (
<div className="container flex flex-col gap-2 py-8">
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Error</AlertTitle>
<AlertDescription>{renderError(error)}</AlertDescription>
</Alert>
</div>
);
}
53 changes: 53 additions & 0 deletions frontend/src/components/RatingInput.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { render, fireEvent, screen } from "@testing-library/react";
import RatingInput from "./RatingInput";
import { beforeEach, describe, test, expect, vi } from "vitest";

describe("RatingInput", () => {
let currentRating: number, setRating: (s: number) => void;

beforeEach(() => {
// Arrange
currentRating = 3;
setRating = vi.fn();
});

test("renders correct number of stars based on currentRating", () => {
render(<RatingInput currentRating={currentRating} setRating={setRating} />);

// Assert
const filledStars = screen.getAllByLabelText(/filled star/i);
const emptyStars = screen.getAllByLabelText(/empty star/i);
expect(filledStars.length).toBe(currentRating);
expect(emptyStars.length).toBe(5 - currentRating);
});

test("updates tempRating on mouse enter and resets on mouse leave", () => {
render(<RatingInput currentRating={currentRating} setRating={setRating} />);

// Act
const fourthStar = screen.getAllByLabelText(/empty star/i)[0];
fireEvent.mouseEnter(fourthStar);

// Assert
const filledStars = screen.getAllByLabelText(/filled star/i);
expect(filledStars.length).toBe(4);

// Act
fireEvent.mouseLeave(fourthStar);

// Assert
const filledStarsAfterLeave = screen.getAllByLabelText(/filled star/i);
expect(filledStarsAfterLeave.length).toBe(currentRating);
});

test("calls setRating with correct value on click", () => {
render(<RatingInput currentRating={currentRating} setRating={setRating} />);

// Act
const secondStar = screen.getAllByLabelText(/filled star/i)[1];
fireEvent.click(secondStar);

// Assert
expect(setRating).toHaveBeenCalledWith(2);
});
});
48 changes: 48 additions & 0 deletions frontend/src/components/RatingInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { cn } from "@/lib/utils";
import { StarIcon } from "lucide-react";
import { useEffect, useState } from "react";

const ratingIcons = [1, 2, 3, 4, 5];

export default function RatingInput({
currentRating,
setRating,
}: {
currentRating: number;
setRating: (rating: number) => void;
}) {
// input with 5 stars that when hovered show the new rating
const [tempRating, setTempRating] = useState(currentRating);
const [hovering, setHovering] = useState(false);

useEffect(() => {
if (!hovering) setTempRating(currentRating);
}, [hovering, currentRating]);

return (
<div
className="flex cursor-pointer"
onMouseEnter={() => setHovering(true)}
onMouseLeave={() => setHovering(false)}
>
{ratingIcons.map((rating) => (
<span
className="px-1 py-2"
onClick={() => setRating(rating)}
key={rating}
onMouseEnter={() => setTempRating(rating)}
>
<StarIcon
aria-label={tempRating >= rating ? "filled star" : "empty star"}
className={cn(
"h-4 w-4",
tempRating >= rating
? "fill-yellow-500 text-yellow-500"
: "fill-gray-400 text-gray-400",
)}
/>
</span>
))}
</div>
);
}
10 changes: 5 additions & 5 deletions frontend/src/components/SearchFilterPopover.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ describe("SearchFilterPopover", () => {
const filterButton = screen.getByRole("button", { name: /filter/i });
fireEvent.click(filterButton); // Open the popover

const italianCheckbox = screen.getByLabelText(/italian/i);
fireEvent.click(italianCheckbox);
const turkishCheckbox = screen.getByLabelText(/turkish/i);
fireEvent.click(turkishCheckbox);

const popoverCloseButton = screen.getByRole("button", { name: /close/i });
fireEvent.click(popoverCloseButton); // Close the popover without confirming
Expand All @@ -55,8 +55,8 @@ describe("SearchFilterPopover", () => {
const filterButton = screen.getByRole("button", { name: /filter/i });
fireEvent.click(filterButton); // Open the popover

const italianCheckbox = screen.getByLabelText(/italian/i);
fireEvent.click(italianCheckbox);
const turkishCheckbox = screen.getByLabelText(/turkish/i);
fireEvent.click(turkishCheckbox);

const meatCheckbox = screen.getByLabelText(/meat/i);
fireEvent.click(meatCheckbox);
Expand All @@ -65,7 +65,7 @@ describe("SearchFilterPopover", () => {
fireEvent.click(confirmButton); // Confirm the selection

// Assert
expect(setCuisine).toHaveBeenCalledWith("Italian");
expect(setCuisine).toHaveBeenCalledWith("Turkish");
expect(setFoodType).toHaveBeenCalledWith("Meat");
});
});
Loading

0 comments on commit eab4b9e

Please sign in to comment.