Skip to content

Commit

Permalink
Merge pull request #32 from neuefische/23-cache-restaurant-data-and-r…
Browse files Browse the repository at this point in the history
…evalidate

23 cache restaurant data and revalidate
  • Loading branch information
josch87 authored Jun 10, 2024
2 parents 3ae75bb + e7c4a9d commit fdc64f0
Show file tree
Hide file tree
Showing 23 changed files with 363 additions and 194 deletions.
28 changes: 27 additions & 1 deletion frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"react-dom": "^18.2.0",
"react-icons": "^5.2.1",
"react-router-dom": "^6.23.1",
"styled-components": "^6.1.11"
"styled-components": "^6.1.11",
"swr": "^2.2.5"
},
"devDependencies": {
"@babel/core": "^7.24.6",
Expand Down
14 changes: 7 additions & 7 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import RestaurantsPage from "./pages/RestaurantsPage/RestaurantsPage.tsx";
import RestaurantDetailsPage from "./pages/RestaurantDetailsPage.tsx";
import ViewRestaurantPage from "./pages/ViewRestaurantPage.tsx";
import { Route, Routes } from "react-router-dom";
import AddRestaurantsPage from "./pages/AddRestaurantsPage.tsx";
import RestaurantEditPage from "./pages/RestaurantEditPage.tsx";
import CreateRestaurantPage from "./pages/CreateRestaurantPage.tsx";
import UpdateRestaurantPage from "./pages/UpdateRestaurantPage.tsx";
import "./App.css";
import RestaurantsPage from "./pages/RestaurantsPage.tsx";

function App() {
return (
<Routes>
<Route path="/" element={<RestaurantsPage />} />
<Route path="/restaurants/add" element={<AddRestaurantsPage />} />
<Route path="/restaurants/edit/:id" element={<RestaurantEditPage />} />
<Route path="/restaurants/:id" element={<RestaurantDetailsPage />} />
<Route path="/restaurants/add" element={<CreateRestaurantPage />} />
<Route path="/restaurants/edit/:id" element={<UpdateRestaurantPage />} />
<Route path="/restaurants/:id" element={<ViewRestaurantPage />} />
</Routes>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled from "styled-components";

export const StyledErrorParagraph = styled.p`
export const StyledErrorContainer = styled.div`
font-size: 0.8rem;
color: var(--error-color);
margin-top: 1rem;
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/components/AlertBox/AlertBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { StyledErrorContainer } from "./AlertBox.styled.ts";
import { ReactNode } from "react";

type AlertBoxProps = {
children: ReactNode;
};

export default function AlertBox({ children }: Readonly<AlertBoxProps>) {
return <StyledErrorContainer>{children}</StyledErrorContainer>;
}
23 changes: 23 additions & 0 deletions frontend/src/components/Button/Button.component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Button from "./Button.tsx";

test("Button component renders a button", () => {
render(
<Button buttonType="delete" handleOnClick={() => {}}>
Delete
</Button>
);
const button = screen.getByRole("button");
expect(button).toBeInTheDocument();
});

test("Button component renders children as text", () => {
render(
<Button buttonType="delete" handleOnClick={() => {}}>
Delete
</Button>
);
const text = screen.getByText(/delete/i);
expect(text).toBeInTheDocument();
});
2 changes: 1 addition & 1 deletion frontend/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default function Button({
children,
handleOnClick,
buttonType,
}: ButtonProps) {
}: Readonly<ButtonProps>) {
return (
<StyledButton $buttonType={buttonType} onClick={handleOnClick}>
{children}
Expand Down
34 changes: 34 additions & 0 deletions frontend/src/components/ButtonLink/ButtonLink.component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import ButtonLink from "./ButtonLink.tsx";
import { MemoryRouter } from "react-router-dom";

test("ButtonLink component renders a link", () => {
render(
<MemoryRouter>
<ButtonLink href="/my-url">Click here</ButtonLink>
</MemoryRouter>
);
const button = screen.getByRole("link");
expect(button).toBeInTheDocument();
});

test("ButtonLink component links to the correct target", () => {
render(
<MemoryRouter>
<ButtonLink href="/my-url">Click here</ButtonLink>
</MemoryRouter>
);
const button = screen.getByRole("link");
expect(button).toHaveAttribute("href", "/my-url");
});

test("ButtonLink component renders children as text", () => {
render(
<MemoryRouter>
<ButtonLink href="/my-url">Click here</ButtonLink>
</MemoryRouter>
);
const text = screen.getByText(/click here/i);
expect(text).toBeInTheDocument();
});
5 changes: 4 additions & 1 deletion frontend/src/components/ButtonLink/ButtonLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ type ButtonLinkProps = {
href: string;
};

export default function ButtonLink({ children, href }: ButtonLinkProps) {
export default function ButtonLink({
children,
href,
}: Readonly<ButtonLinkProps>) {
return <StyledLink to={href}>{children}</StyledLink>;
}
9 changes: 9 additions & 0 deletions frontend/src/components/Logo/Logo.component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Logo from "./Logo.tsx";

test("Button component renders a button", () => {
render(<Logo />);
const button = screen.getByText(/restaurantapp/i);
expect(button).toBeInTheDocument();
});
4 changes: 3 additions & 1 deletion frontend/src/components/RestaurantCard/RestaurantCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ type RestaurantCardProps = {
restaurant: RestaurantType;
};

export default function RestaurantCard({ restaurant }: RestaurantCardProps) {
export default function RestaurantCard({
restaurant,
}: Readonly<RestaurantCardProps>) {
return (
<StyledArticle>
<StyledImageContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type RestaurantCardDetailProps = {
export default function RestaurantCardDetail({
icon,
value,
}: RestaurantCardDetailProps) {
}: Readonly<RestaurantCardDetailProps>) {
return (
<StyledDetailContainer>
<div>{icon}</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type RestaurantCardListProps = {

export default function RestaurantCardList({
restaurants,
}: RestaurantCardListProps) {
}: Readonly<RestaurantCardListProps>) {
return (
<StyledUnorderedList>
{restaurants.map((restaurant) => {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/RestaurantForm/RestaurantForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type RestaurantFormProps = {
export default function RestaurantForm({
restaurantData,
onSubmit,
}: RestaurantFormProps) {
}: Readonly<RestaurantFormProps>) {
const initialFieldValidation = {
title: "",
city: "",
Expand Down Expand Up @@ -62,6 +62,7 @@ export default function RestaurantForm({
onChange={handleUserInput}
value={formData.title}
required
autoFocus
/>
<StyledFieldError>{fieldValidation.title}</StyledFieldError>
</StyledFormRow>
Expand Down
64 changes: 64 additions & 0 deletions frontend/src/data/restaurantData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import useSWR from "swr";
import { RestaurantType } from "../model/Restaurant.ts";
import axios from "axios";
import { logtail } from "../logger.ts";

export function useRestaurants() {
const { data, error, isLoading } = useSWR<RestaurantType[]>(
"/api/restaurants",
(url: string) => {
logtail.info(`Trying to receive all restaurants from ${url}`);

return axios
.get(url)
.then((response) => {
logtail.info("Received " + response.data.length + " restaurants");
return response.data;
})
.catch((error) => {
logtail.error(error.message, {
error: error,
});
throw error;
});
}
);

return {
restaurants: data,
isLoading,
isError: error,
};
}

export function useRestaurant(id: string) {
if (!id) {
throw new Error("Restaurant ID is required!");
}

const { data, error, isLoading } = useSWR<RestaurantType>(
`/api/restaurants/${id}`,
(url: string) => {
logtail.info(`Trying to receive restaurant from ${url}`);

return axios
.get(url)
.then((response) => {
logtail.info(`Received restaurant with ID ${response.data.id}`);
return response.data;
})
.catch((error) => {
logtail.error(error.message, {
error: error,
});
throw error;
});
}
);

return {
restaurant: data,
isLoading,
isError: error,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import axios from "axios";
import { useNavigate } from "react-router-dom";
import { NewRestaurantDTOType, RestaurantType } from "../model/Restaurant.ts";
import { logtail } from "../logger.ts";
import { mutate } from "swr";

export default function AddRestaurantsPage() {
export default function CreateRestaurantPage() {
const navigate = useNavigate();

function handleAddRestaurant(formData: NewRestaurantDTOType) {
Expand All @@ -16,6 +17,7 @@ export default function AddRestaurantsPage() {
.then((response) => {
const savedRestaurant: RestaurantType = response.data;
logtail.info("Created new restaurant with ID " + savedRestaurant.id);
mutate("/api/restaurants");
navigate("/restaurants/" + savedRestaurant.id);
})
.catch((error) => {
Expand Down
57 changes: 0 additions & 57 deletions frontend/src/pages/RestaurantDetailsPage.tsx

This file was deleted.

Loading

0 comments on commit fdc64f0

Please sign in to comment.