mirror of
https://github.com/bubblecup-12/VogelSocialMedia.git
synced 2025-07-06 05:18:48 +00:00
flappy Bird
This commit is contained in:
parent
90a4a5fd59
commit
9f9a21818a
13 changed files with 397 additions and 67 deletions
|
@ -5,7 +5,7 @@ import { Request, Response, NextFunction } from "express";
|
||||||
// Configure multer to store files in memory
|
// Configure multer to store files in memory
|
||||||
const multerInstance = multer({
|
const multerInstance = multer({
|
||||||
storage: multer.memoryStorage(),
|
storage: multer.memoryStorage(),
|
||||||
limits: { fileSize: 5 * 1024 * 1024 }, // Limit file size to 5 MB
|
limits: { fileSize: 30 * 1024 * 1024 }, // Limit file size to 30 MB
|
||||||
});
|
});
|
||||||
|
|
||||||
export const upload = (req: Request, res: Response, next: NextFunction) => {
|
export const upload = (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { StatusCodes } from "http-status-codes";
|
||||||
|
|
||||||
const multerInstance = multer({
|
const multerInstance = multer({
|
||||||
storage: multer.memoryStorage(),
|
storage: multer.memoryStorage(),
|
||||||
limits: { fileSize: 5 * 1024 * 1024 }, // 5 MB
|
limits: { fileSize: 30 * 1024 * 1024 }, // 30 MB
|
||||||
});
|
});
|
||||||
|
|
||||||
export const upload = (req: Request, res: Response, next: NextFunction) => {
|
export const upload = (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
|
|
@ -11,7 +11,7 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- pgdata:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "pg_isready", "-U", "postgres"]
|
test: ["CMD", "pg_isready", "-U", "${DB_USER}"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|
BIN
code/frontend/public/assets/images/flapp.png
Normal file
BIN
code/frontend/public/assets/images/flapp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 128 KiB |
BIN
code/frontend/public/assets/images/flipp.png
Normal file
BIN
code/frontend/public/assets/images/flipp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 KiB |
BIN
code/frontend/public/assets/images/logoWithoutStick.png
Normal file
BIN
code/frontend/public/assets/images/logoWithoutStick.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 140 KiB |
|
@ -1,6 +1,6 @@
|
||||||
.App {
|
.App {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
min-height: 100vh;
|
min-height: calc(100vh - var(--header-height));
|
||||||
}
|
}
|
||||||
|
|
||||||
.App-logo {
|
.App-logo {
|
||||||
|
|
|
@ -8,32 +8,31 @@ import Header from "./components/Header";
|
||||||
import Profile from "./pages/Profile";
|
import Profile from "./pages/Profile";
|
||||||
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
||||||
import { Auth } from "./api/Auth";
|
import { Auth } from "./api/Auth";
|
||||||
|
import { NotFound } from "./pages/404Page/NotFoundPage";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<Auth>
|
<Auth>
|
||||||
<Router>
|
<Router>
|
||||||
<div className="App">
|
<Header />
|
||||||
<Header />
|
<div className="App">
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route path="*" element={<NotFound />} />
|
||||||
path="/login"
|
<Route
|
||||||
element={<LoginAndSignUpPage signupProp={false} />}
|
path="/login"
|
||||||
></Route>
|
element={<LoginAndSignUpPage signupProp={false} />}
|
||||||
<Route
|
></Route>
|
||||||
path="/register"
|
<Route
|
||||||
element={<LoginAndSignUpPage signupProp={true} />}
|
path="/register"
|
||||||
></Route>
|
element={<LoginAndSignUpPage signupProp={true} />}
|
||||||
<Route path="/profile" element={<Profile />}></Route>
|
></Route>
|
||||||
</Routes>
|
<Route path="/profile" element={<Profile />}></Route>
|
||||||
<Footer />
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</Router>
|
<Footer />
|
||||||
</Auth>
|
</Router>
|
||||||
);
|
</Auth>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { refreshToken } from "./refreshToken";
|
import { refreshToken } from "./refreshToken";
|
||||||
|
|
||||||
const excludedUrls: string[] = ["/user/login", "/user/regiser"];
|
const excludedUrls: string[] = ["/user/login", "/user/register"];
|
||||||
|
|
||||||
const api = axios.create({
|
const api = axios.create({
|
||||||
baseURL: "http://localhost:3001/api",
|
baseURL: "http://localhost:3001/api",
|
||||||
|
|
|
@ -1,59 +1,59 @@
|
||||||
.base-header {
|
.base-header {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: var(--header-height);
|
height: var(--header-height);
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
border-radius: 0rem !important;
|
border-radius: 0rem !important;
|
||||||
}
|
}
|
||||||
@media only screen and (min-width: 768px) {
|
@media only screen and (min-width: 768px) {
|
||||||
.base-header {
|
.base-header {
|
||||||
height: var(--header-height);
|
height: var(--header-height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-title {
|
.header-title {
|
||||||
color: var(--Rotkehlchen-orange-default);
|
color: var(--Rotkehlchen-orange-default);
|
||||||
}
|
}
|
||||||
.header-icon-feather {
|
.header-icon-feather {
|
||||||
height: 35px;
|
height: 35px;
|
||||||
}
|
}
|
||||||
.header-icon-menu {
|
.header-icon-menu {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-icon {
|
.header-icon {
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
@media only screen and (min-width: 768px) {
|
@media only screen and (min-width: 768px) {
|
||||||
.header-icon {
|
.header-icon {
|
||||||
margin: 40px;
|
margin: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-list {
|
.drawer-list {
|
||||||
background-color: var(--dark-blue);
|
background-color: var(--dark-blue);
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
min-width: 13rem;
|
min-width: 13rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-list-item {
|
.drawer-list-item {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-list-item-button {
|
.drawer-list-item-button {
|
||||||
height: 10vh;
|
height: 10vh;
|
||||||
}
|
}
|
||||||
.drawer-list-item-button:hover {
|
.drawer-list-item-button:hover {
|
||||||
background-color: var(--dark-blue-hover);
|
background-color: var(--dark-blue-hover);
|
||||||
}
|
}
|
||||||
|
|
243
code/frontend/src/pages/404Page/NotFoundPage.tsx
Normal file
243
code/frontend/src/pages/404Page/NotFoundPage.tsx
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import "./notFound.css";
|
||||||
|
import ButtonPrimary from "../../components/ButtonRotkehlchen";
|
||||||
|
|
||||||
|
type Block = {
|
||||||
|
x: number;
|
||||||
|
height: number;
|
||||||
|
passed: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const GAP = 300;
|
||||||
|
const BLOCK_WIDTH = 60;
|
||||||
|
const GRAVITY = 0.2;
|
||||||
|
const FLAP_VELOCITY = -8;
|
||||||
|
const BIRD_SIZE = 25;
|
||||||
|
const BLOCK_SPAWN_DISTANCE = 400; // px
|
||||||
|
|
||||||
|
export const NotFound = () => {
|
||||||
|
const screenWidth = window.innerWidth;
|
||||||
|
const screenHeight = window.innerHeight;
|
||||||
|
|
||||||
|
const targetRef = useRef<HTMLSpanElement>(null);
|
||||||
|
const gameRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const [score, setScore] = useState(0);
|
||||||
|
const [gameOver, setGameOver] = useState(false);
|
||||||
|
const [hasStarted, setHasStarted] = useState(false);
|
||||||
|
const [textPos, setTextPos] = useState<number>(screenWidth / 2);
|
||||||
|
const [rotation, setRotation] = useState(0);
|
||||||
|
const [renderBlocks, setRenderBlocks] = useState<Block[]>([]);
|
||||||
|
const [birdPos, setBirdPos] = useState({ x: 0, y: 0 });
|
||||||
|
|
||||||
|
const distanceSinceLastBlock = useRef(0);
|
||||||
|
const speedRef = useRef(2);
|
||||||
|
const birdPosRef = useRef({ x: 0, y: 0 });
|
||||||
|
const velocityRef = useRef(0);
|
||||||
|
const blocksRef = useRef<Block[]>([]);
|
||||||
|
const scoreRef = useRef(0);
|
||||||
|
const hasStartedRef = useRef(hasStarted);
|
||||||
|
const gameOverRef = useRef(gameOver);
|
||||||
|
const textPosRef = useRef(textPos);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (targetRef.current && gameRef.current) {
|
||||||
|
const rect = targetRef.current.getBoundingClientRect();
|
||||||
|
const gameBox = gameRef.current.getBoundingClientRect();
|
||||||
|
const yPos = rect.top - gameBox.top;
|
||||||
|
const x = rect.left + rect.width / 2;
|
||||||
|
const y = yPos + 15;
|
||||||
|
birdPosRef.current = { x, y };
|
||||||
|
setBirdPos({ x, y });
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.code === "Space") {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!gameOverRef.current) {
|
||||||
|
setHasStarted(true);
|
||||||
|
hasStartedRef.current = true;
|
||||||
|
velocityRef.current = FLAP_VELOCITY;
|
||||||
|
}
|
||||||
|
} else if (e.code === "Enter") {
|
||||||
|
e.preventDefault();
|
||||||
|
if (gameOverRef.current) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
} else if (e.code === "KeyR") {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let lastBlockTime = Date.now();
|
||||||
|
let animationId: number;
|
||||||
|
|
||||||
|
function loop() {
|
||||||
|
if (!hasStartedRef.current || gameOverRef.current) {
|
||||||
|
setRenderBlocks([...blocksRef.current]);
|
||||||
|
setBirdPos({ ...birdPosRef.current });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
velocityRef.current += GRAVITY;
|
||||||
|
birdPosRef.current.y += velocityRef.current;
|
||||||
|
setRotation(Math.max(Math.min(velocityRef.current * 2, 90), -15));
|
||||||
|
|
||||||
|
textPosRef.current -= speedRef.current;
|
||||||
|
setTextPos(textPosRef.current);
|
||||||
|
|
||||||
|
distanceSinceLastBlock.current += speedRef.current;
|
||||||
|
|
||||||
|
if (distanceSinceLastBlock.current >= BLOCK_SPAWN_DISTANCE) {
|
||||||
|
const blockHeight = Math.random() * (screenHeight - GAP - 100) + 50;
|
||||||
|
blocksRef.current.push({
|
||||||
|
x: screenWidth,
|
||||||
|
height: blockHeight,
|
||||||
|
passed: false,
|
||||||
|
});
|
||||||
|
distanceSinceLastBlock.current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blocksRef.current = blocksRef.current
|
||||||
|
.map((block) => {
|
||||||
|
const newX = block.x - speedRef.current;
|
||||||
|
let passed = block.passed;
|
||||||
|
|
||||||
|
if (
|
||||||
|
newX <= birdPosRef.current.x + BIRD_SIZE &&
|
||||||
|
newX + BLOCK_WIDTH >= birdPosRef.current.x - BIRD_SIZE
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
birdPosRef.current.y + BIRD_SIZE >= block.height + GAP ||
|
||||||
|
birdPosRef.current.y - BIRD_SIZE <= block.height
|
||||||
|
) {
|
||||||
|
setGameOver(true);
|
||||||
|
gameOverRef.current = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!passed &&
|
||||||
|
newX + BLOCK_WIDTH < birdPosRef.current.x - BIRD_SIZE
|
||||||
|
) {
|
||||||
|
scoreRef.current += 1;
|
||||||
|
speedRef.current += 0.1;
|
||||||
|
setScore(scoreRef.current);
|
||||||
|
passed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...block, x: newX, passed };
|
||||||
|
})
|
||||||
|
.filter((block) => block.x + BLOCK_WIDTH > 0);
|
||||||
|
|
||||||
|
if (
|
||||||
|
birdPosRef.current.y >= screenHeight - BIRD_SIZE ||
|
||||||
|
birdPosRef.current.y <= 0
|
||||||
|
) {
|
||||||
|
setGameOver(true);
|
||||||
|
gameOverRef.current = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRenderBlocks([...blocksRef.current]);
|
||||||
|
setBirdPos({ ...birdPosRef.current });
|
||||||
|
|
||||||
|
if (!gameOverRef.current) {
|
||||||
|
animationId = requestAnimationFrame(loop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasStarted) {
|
||||||
|
hasStartedRef.current = true;
|
||||||
|
gameOverRef.current = false;
|
||||||
|
animationId = requestAnimationFrame(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => cancelAnimationFrame(animationId);
|
||||||
|
}, [hasStarted]);
|
||||||
|
|
||||||
|
const handleGameClick = () => {
|
||||||
|
if (gameOver) return;
|
||||||
|
if (!hasStarted) {
|
||||||
|
setHasStarted(true);
|
||||||
|
hasStartedRef.current = true;
|
||||||
|
velocityRef.current = FLAP_VELOCITY;
|
||||||
|
} else {
|
||||||
|
velocityRef.current = FLAP_VELOCITY;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const birdSprite =
|
||||||
|
velocityRef.current === 0
|
||||||
|
? "/assets/images/logoWithoutStick.png"
|
||||||
|
: velocityRef.current > 0
|
||||||
|
? "/assets/images/flipp.png"
|
||||||
|
: "/assets/images/flapp.png";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="game-container" ref={gameRef} onClick={handleGameClick}>
|
||||||
|
<img
|
||||||
|
src={birdSprite}
|
||||||
|
className="bird"
|
||||||
|
style={{
|
||||||
|
top: birdPos.y,
|
||||||
|
left: birdPos.x,
|
||||||
|
transform: `translate(-50%, -50%) rotate(${rotation}deg)`,
|
||||||
|
}}
|
||||||
|
alt="bird"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="text"
|
||||||
|
style={{
|
||||||
|
left: textPos,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h1 key={"404"}>
|
||||||
|
4<span ref={targetRef}>0</span>4 Not Found
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
{hasStarted && !gameOver && (
|
||||||
|
<div className="points body-l">Score: {score}</div>
|
||||||
|
)}
|
||||||
|
{renderBlocks.map((block, index) => (
|
||||||
|
<React.Fragment key={index}>
|
||||||
|
<div
|
||||||
|
className="tree-trunk top"
|
||||||
|
style={{
|
||||||
|
top: 0,
|
||||||
|
left: block.x,
|
||||||
|
width: BLOCK_WIDTH,
|
||||||
|
height: block.height,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
className="tree-trunk bottom"
|
||||||
|
style={{
|
||||||
|
top: block.height + GAP,
|
||||||
|
left: block.x,
|
||||||
|
width: BLOCK_WIDTH,
|
||||||
|
height: screenHeight - block.height - GAP,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
{gameOver && (
|
||||||
|
<div className="gameOver small-title">
|
||||||
|
<h1>You have killed the bird</h1>
|
||||||
|
<p>Your Score is {score}</p>
|
||||||
|
<ButtonPrimary
|
||||||
|
style="primary"
|
||||||
|
label="restart"
|
||||||
|
type="reset"
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
81
code/frontend/src/pages/404Page/notFound.css
Normal file
81
code/frontend/src/pages/404Page/notFound.css
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
.text {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin: 0;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: white;
|
||||||
|
font-size: 48px;
|
||||||
|
font-weight: bold;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
.game-container {
|
||||||
|
width: 100vw;
|
||||||
|
height: calc(100vh - var(--header-height));
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bird {
|
||||||
|
position: relative;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(0, -10px);
|
||||||
|
color: black;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.points {
|
||||||
|
position: fixed;
|
||||||
|
top: 70px;
|
||||||
|
left: 10px;
|
||||||
|
background-color: var(--Rotkehlchen-gray);
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
.gameOver {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: rgba(13, 10, 56, 0.71);
|
||||||
|
color: white;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
|
||||||
|
text-align: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.tree-trunk {
|
||||||
|
width: 60px;
|
||||||
|
position: absolute;
|
||||||
|
background: repeating-linear-gradient(
|
||||||
|
45deg,
|
||||||
|
#8b5a2b,
|
||||||
|
#8b5a2b 10px,
|
||||||
|
#a0522d 10px,
|
||||||
|
#a0522d 20px
|
||||||
|
);
|
||||||
|
|
||||||
|
box-shadow: inset 0 0 10px #5c4033;
|
||||||
|
}
|
||||||
|
.bottom {
|
||||||
|
border-start-start-radius: 20px;
|
||||||
|
border-start-end-radius: 20px;
|
||||||
|
}
|
||||||
|
.top {
|
||||||
|
border-end-start-radius: 20px;
|
||||||
|
border-end-end-radius: 20px;
|
||||||
|
}
|
|
@ -44,12 +44,12 @@ function LoginAndSignUpPage({ signupProp }: { signupProp: boolean }) {
|
||||||
setErrorMessages(undefined);
|
setErrorMessages(undefined);
|
||||||
try {
|
try {
|
||||||
const response = signup
|
const response = signup
|
||||||
? await api.post("http://localhost:3001/api/user/register", {
|
? await api.post("/user/register", {
|
||||||
email: formData.email,
|
email: formData.email,
|
||||||
username: formData.username,
|
username: formData.username,
|
||||||
password: formData.password,
|
password: formData.password,
|
||||||
})
|
})
|
||||||
: await api.post("http://localhost:3001/api/user/login", {
|
: await api.post("/user/login", {
|
||||||
username: formData.username,
|
username: formData.username,
|
||||||
password: formData.password,
|
password: formData.password,
|
||||||
});
|
});
|
||||||
|
@ -65,7 +65,14 @@ function LoginAndSignUpPage({ signupProp }: { signupProp: boolean }) {
|
||||||
await setUserState();
|
await setUserState();
|
||||||
navigate(returnTo, { replace: true });
|
navigate(returnTo, { replace: true });
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setErrorMessages(err.response.data);
|
if (err.response?.data) {
|
||||||
|
setErrorMessages(err.response.data);
|
||||||
|
} else {
|
||||||
|
setErrorMessages({
|
||||||
|
error: "Error",
|
||||||
|
details: [{ message: err.message || "Something went wrong." }],
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,10 +149,10 @@ function LoginAndSignUpPage({ signupProp }: { signupProp: boolean }) {
|
||||||
minLength={signup ? 8 : undefined}
|
minLength={signup ? 8 : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{errorMessages && (
|
{errorMessages && errorMessages?.details?.length > 0 && (
|
||||||
<div className="error-messages">
|
<div className="error-messages">
|
||||||
{errorMessages.details.map((detial, index) => (
|
{errorMessages.details.map((detail, index) => (
|
||||||
<p key={index}>{detial.message}</p>
|
<p key={index}>{detail.message}</p>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue