diff --git a/backend/routers/comments.py b/backend/routers/comments.py index 0e44fbdd2307fd2ae3fa1554693f66b87b6476fe..35808993272cc1b7290d93bfd1bc55f2ae6fdf55 100644 --- a/backend/routers/comments.py +++ b/backend/routers/comments.py @@ -1,24 +1,24 @@ -from fastapi import APIRouter, Depends -from sqlalchemy.orm import Session -from typing import List - -from db import schemas, crud -from db.database import get_db - - -router = APIRouter(prefix="/api/comments", tags=["comments"]) - - -@router.get('/{place}', response_model=List[schemas.Comment]) -async def get_comments(place: str, page: int = 1, db: Session = Depends(get_db)): - return crud.get_comments(place, page, db) - - -@router.post('/{place}', response_model=schemas.Comment) -async def create_comment(place: str, comment: schemas.CommentBase, db: Session = Depends(get_db)): - return crud.create_comment(place, comment, db) - - -@router.delete('/{id}', response_model=None) -async def delete_comment(id: int, db: Session = Depends(get_db)): - return crud.delete_comment(id, db) +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from typing import List + +from db import schemas, crud +from db.database import get_db + + +router = APIRouter(prefix="/api", tags=["comments"]) + + +@router.get('/{place}/comments', response_model=List[schemas.Comment]) +async def get_comments(place: str, page: int = 1, db: Session = Depends(get_db)): + return crud.get_comments(place, page, db) + + +@router.post('/{place}/comments', response_model=schemas.Comment) +async def create_comment(place: str, comment: schemas.CommentBase, db: Session = Depends(get_db)): + return crud.create_comment(place, comment, db) + + +@router.delete('/comments/{id}', response_model=None) +async def delete_comment(id: int, db: Session = Depends(get_db)): + return crud.delete_comment(id, db) diff --git a/backend/routers/news.py b/backend/routers/news.py index 8e8ecfb3d378c544ca009ade182954dd65a41dbd..2dcc7e224d0061565ddf5c9f759c7cd0822939e4 100644 --- a/backend/routers/news.py +++ b/backend/routers/news.py @@ -1,24 +1,24 @@ -from fastapi import APIRouter, Depends -from sqlalchemy.orm import Session -from typing import List - -from db import schemas, crud -from db.database import get_db - - -router = APIRouter(prefix="/api/news", tags=["news"]) - - -@router.get('/{place}', response_model=List[schemas.News]) -async def get_news(place: str, db: Session = Depends(get_db)): - return crud.get_news(place, db) - - -@router.post('/{place}', response_model=schemas.News) -async def create_news(place: str, news: schemas.NewsBase, db: Session = Depends(get_db)): - return crud.create_news(place, news, db) - - -@router.delete('/{id}', response_model=None) -async def delete_news(id: int, db: Session = Depends(get_db)): - return crud.delete_news(id, db) +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from typing import List + +from db import schemas, crud +from db.database import get_db + + +router = APIRouter(prefix="/api", tags=["news"]) + + +@router.get('/{place}/news', response_model=List[schemas.News]) +async def get_news(place: str, db: Session = Depends(get_db)): + return crud.get_news(place, db) + + +@router.post('/{place}/news', response_model=schemas.News) +async def create_news(place: str, news: schemas.NewsBase, db: Session = Depends(get_db)): + return crud.create_news(place, news, db) + + +@router.delete('/news/{id}', response_model=None) +async def delete_news(id: int, db: Session = Depends(get_db)): + return crud.delete_news(id, db) diff --git a/frontend/.prettierrc b/frontend/.prettierrc index a101b85e1758af1f7d3723885de59251cc51303c..ce10c4320e4e3fa8fe78b9f7407d3f3ddae6f757 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -1,10 +1,11 @@ -{ - "singleQuote": false, - "trailingComma": "all", - "semi": true, - "tabWidth": 2, - "useTabs": false, - "printWidth": 100, - "bracketSpacing": true - } +{ + "singleQuote": false, + "trailingComma": "all", + "semi": true, + "tabWidth": 2, + "useTabs": false, + "printWidth": 100, + "bracketSpacing": true, + "endOfLine": "auto" +} \ No newline at end of file diff --git a/frontend/src/components/Comments.js b/frontend/src/components/Comments.js new file mode 100644 index 0000000000000000000000000000000000000000..638e600ace69a7ff53eb7d2945abc8b1a4506302 --- /dev/null +++ b/frontend/src/components/Comments.js @@ -0,0 +1,26 @@ +import React, { useEffect, useState } from "react"; +import axios from "axios"; + +export default function Comments({ place }) { + const [comments, setComments] = useState([]); + + useEffect(() => { + axios + .get(`${process.env.REACT_APP_BASE_URL_BACK}/${place}/comments`) + .then((res) => { + setComments(res.data); + }) + .catch((e) => console.log(e)); + }); + + return ( + <div style={{ width: "25%", overflowY: "scroll" }}> + {comments.map((comment, index) => ( + <div key={index} style={{ display: "flex", flexDirection: "column", border: "solid black 1px", borderRadius: "0.5rem", margin: "1rem", padding: "0.5rem" }}> + <div style={{marginBottom: "0.5rem", textAlign: "left"}}>{comment.comment}</div> + <div style={{fontSize: "0.7rem", alignSelf: "flex-start", marginLeft: "0.2rem"}}>{comment.date.split("T").reduce((date, hours) => `À ${hours.substring(0,5)} le ${date}`)}</div> + </div> + ))} + </div> + ); +} diff --git a/frontend/src/components/Footer.js b/frontend/src/components/Footer.js index d8f8a8f516c48dd99b443104929e4549cf7d7c5f..9d4b1a3d33afcc01c97ed06c460e8f708fe7b8af 100644 --- a/frontend/src/components/Footer.js +++ b/frontend/src/components/Footer.js @@ -5,7 +5,7 @@ import "../styles/Footer.css"; export default function Footer() { return ( <footer className="footer"> - <div className="py-4 bg-dark flex-shrink-0"> + <div className="py-2 bg-dark"> <div className="container text-center"> Fait par{" "} <a href="https://viarezo.fr" className="VR-link"> diff --git a/frontend/src/components/Graph.js b/frontend/src/components/Graph.js index 37d35cc4165ea8058eb344d7f97fe896421642ca..cf9e766ffb94033bdd579962f89d8ac8a62fe1a7 100644 --- a/frontend/src/components/Graph.js +++ b/frontend/src/components/Graph.js @@ -57,63 +57,59 @@ export default function DailyGraph({ }; return ( - <div> + <> <div className="graph-title"> Temps d'attente pour le prochain créneau d'ouverture </div> - <div className="parent"> - <div className="graph"> - <ResponsiveContainer width="100%" height="100%"> - <AreaChart - width={500} - height={300} - data={data} - margin={{ - top: 5, - right: 30, - left: 20, - bottom: 5, - }} - > - <defs> - <linearGradient id="colorGradient" x1="0" y1="0" x2="0" y2="1"> - <stop offset="${2 * temp}%" stopColor="#ff0000" stopOpacity={0.55} /> - <stop offset="50%" stopColor="#fff200" stopOpacity={0.5} /> - <stop offset="90%" stopColor="#1e9600" stopOpacity={0.35} /> - </linearGradient> - </defs> - <CartesianGrid stroke="#FFFFFF" strokeDasharray="1 3" /> - <XAxis - axisLine={false} - tickLine={false} - tick={{ fill: "#FFFFFF", fontSize: "18" }} - dataKey="name" - /> - <YAxis - axisLine={false} - tickLine={false} - tick={{ fill: "#FFFFFF", fontSize: "18" }} - tickInt - tickCount={10} - dataKey="time" - domain={[0, (dataMax) => 10 * Math.floor((dataMax + 10) / 10)]} - allowDecimals={false} - name="Temps d'attente" - /> - <Tooltip content={<CustomTooltip />} /> - <Area - type="monotone" - dataKey="time" - stroke="#FFFFFF" - strokeWidth={1} - fillOpacity={1} - fill="url(#colorGradient)" - dot={{ stroke: "#0967D2", strokeWidth: 2, fill: "#fff" }} - /> - </AreaChart> - </ResponsiveContainer> - </div> + <div className="graph"> + <ResponsiveContainer width="100%" height="100%"> + <AreaChart + data={data} + margin={{ + top: 5, + right: 30, + left: 20, + bottom: 5, + }} + > + <defs> + <linearGradient id="colorGradient" x1="0" y1="0" x2="0" y2="1"> + <stop offset="${2 * temp}%" stopColor="#ff0000" stopOpacity={0.55} /> + <stop offset="50%" stopColor="#fff200" stopOpacity={0.5} /> + <stop offset="90%" stopColor="#1e9600" stopOpacity={0.35} /> + </linearGradient> + </defs> + <CartesianGrid stroke="#FFFFFF" strokeDasharray="1 3" /> + <XAxis + axisLine={false} + tickLine={false} + tick={{ fill: "#FFFFFF", fontSize: "18" }} + dataKey="name" + /> + <YAxis + axisLine={false} + tickLine={false} + tick={{ fill: "#FFFFFF", fontSize: "18" }} + tickInt + tickCount={10} + dataKey="time" + domain={[0, (dataMax) => 10 * Math.floor((dataMax + 10) / 10)]} + allowDecimals={false} + name="Temps d'attente" + /> + <Tooltip content={<CustomTooltip />} /> + <Area + type="monotone" + dataKey="time" + stroke="#FFFFFF" + strokeWidth={1} + fillOpacity={1} + fill="url(#colorGradient)" + dot={{ stroke: "#0967D2", strokeWidth: 2, fill: "#fff" }} + /> + </AreaChart> + </ResponsiveContainer> </div> - </div> + </> ); } diff --git a/frontend/src/components/WaitingTime.js b/frontend/src/components/WaitingTime.js index f8b93651cc898dd8da21c1f20b44805db43c6125..4d466ee1b1503c7f55143f896a08e73226a9cc24 100644 --- a/frontend/src/components/WaitingTime.js +++ b/frontend/src/components/WaitingTime.js @@ -17,12 +17,15 @@ export default function WaitingTime({ place }) { }); }, [url]); - if (!post) return null; return ( <div className="parent"> - <div className="waiting-time"> - Temps d'attente estimé à <b>{post} minutes</b>. - </div> + {post ? ( + <div className="waiting-time"> + Temps d'attente estimé à <b>{post} minutes</b>. + </div> + ) : ( + <div>Pas de données...</div> + )} </div> ); } diff --git a/frontend/src/components/index.js b/frontend/src/components/index.js index eb7173cd7e3b307b78d63fdb0685edc17644a6ba..76758d28d9f9c9649ce6125ea0b07e3862024fb3 100644 --- a/frontend/src/components/index.js +++ b/frontend/src/components/index.js @@ -3,3 +3,4 @@ export { default as Footer } from "./Footer"; export { default as Timetable } from "./Timetable"; export { default as WaitingTime } from "./WaitingTime"; export { default as DailyGraph } from "./Graph"; +export { default as Comments } from "./Comments"; diff --git a/frontend/src/index.js b/frontend/src/index.js index 101fcfe7a2cad3fe1049cecd5453cde23b682987..ea8b8187913b74e830d39bea8fe654410f638944 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -10,7 +10,7 @@ import "./styles/index.css"; export default function App() { return ( - <div className="App"> + <div className="app"> <Router> <Header /> <div className="page"> diff --git a/frontend/src/styles/Footer.css b/frontend/src/styles/Footer.css index 6dc0fdf45ffff4d7c40efaf7d27fea618e4a6ca6..85c9ab3d87fd7bc821df9b532a064b0588ee0b4b 100644 --- a/frontend/src/styles/Footer.css +++ b/frontend/src/styles/Footer.css @@ -1,6 +1,5 @@ .footer{ width: 100%; - margin-top: 100px; } .VR-link{ diff --git a/frontend/src/styles/Graph.css b/frontend/src/styles/Graph.css index beec63a5ef22d689f3dde1f17c9e3760d015aa59..c3991fac2cd50dd6ce127b028f0b65ab3ceaeaa9 100644 --- a/frontend/src/styles/Graph.css +++ b/frontend/src/styles/Graph.css @@ -1,16 +1,10 @@ -.parent{ - display: flex; - justify-content: center -} - - .graph-title{ display: inline-block; text-align: center; } .graph{ - height: 20em; - width: 40em; + height: 100%; + width: 100%; display: inline-block; } \ No newline at end of file diff --git a/frontend/src/styles/Timetable.css b/frontend/src/styles/Timetable.css index fe1502d0f2a997b15688af8b280bbe5cbc773c55..595feb386391a884990cabef5d60f02e68a62a8e 100644 --- a/frontend/src/styles/Timetable.css +++ b/frontend/src/styles/Timetable.css @@ -1,7 +1,5 @@ -.timetable{ - display: inline-block; - border-radius: 5px; - width: 500px; - text-align: center; - margin-top: 50px; +.timetable{ + display: inline-block; + border-radius: 5px; + text-align: center; } \ No newline at end of file diff --git a/frontend/src/styles/eiffel.css b/frontend/src/styles/eiffel.css new file mode 100644 index 0000000000000000000000000000000000000000..46fd353b1266682dabdd59bf3b3adbc1ce93ac83 --- /dev/null +++ b/frontend/src/styles/eiffel.css @@ -0,0 +1,11 @@ +.eiffel-container { + display: flex; + height: 100%; +} + +#eiffel-main-page { + width: 75%; + flex-direction: column; + justify-content: space-between; + align-content: center; +} \ No newline at end of file diff --git a/frontend/src/styles/index.css b/frontend/src/styles/index.css index a6fa11fa4a4c102b0fa403230cffd7d159e54bcf..d279aa8580f75795dcf09104d84c07095f592728 100644 --- a/frontend/src/styles/index.css +++ b/frontend/src/styles/index.css @@ -9,10 +9,10 @@ body, html { flex-direction: column; justify-content: space-between; width: 100vw; - min-height: 100%; + height: 100vh; } .page{ - height: 100vh; flex: 1; + overflow: hidden; } diff --git a/frontend/src/views/Eiffel.js b/frontend/src/views/Eiffel.js index 7525dd666a79a9d646103662b8530d8b8f97a292..c5c852acb591b9711176f65d171706ee14aab7c4 100644 --- a/frontend/src/views/Eiffel.js +++ b/frontend/src/views/Eiffel.js @@ -1,35 +1,40 @@ import React from "react"; -import { DailyGraph, Timetable, WaitingTime } from "../components"; +import { DailyGraph, Timetable, WaitingTime, Comments } from "../components"; + +import "../styles/eiffel.css"; export default function Eiffel() { return ( - <div> - <h2>RU Eiffel</h2> - <WaitingTime place="eiffel" /> - <DailyGraph - place="eiffel" - day={3} - min_time_hour={12} - min_time_mn={0} - max_time_hour={12} - max_time_mn={40} - interval={300} - /> - <Timetable - schedule={{ - LundiMidi: "11h30 - 14h", - LundiSoir: "18h30 - 21h", - MardiMidi: "11h30 - 14h", - MardiSoir: "18h30 - 21h", - MercrediMidi: "11h30 - 14h", - MercrediSoir: "18h30 - 21h", - JeudiMidi: "11h30 - 14h", - JeudiSoir: "18h30 - 21h", - VendrediMidi: "11h30 - 14h", - VendrediSoir: "18h30 - 21h", - }} - /> + <div className="eiffel-container"> + <div className="eiffel-container" id="eiffel-main-page"> + <h2>RU Eiffel</h2> + <WaitingTime place="eiffel" /> + <DailyGraph + place="eiffel" + day={3} + min_time_hour={12} + min_time_mn={0} + max_time_hour={12} + max_time_mn={40} + interval={300} + /> + <Timetable + schedule={{ + LundiMidi: "11h30 - 14h", + LundiSoir: "18h30 - 21h", + MardiMidi: "11h30 - 14h", + MardiSoir: "18h30 - 21h", + MercrediMidi: "11h30 - 14h", + MercrediSoir: "18h30 - 21h", + JeudiMidi: "11h30 - 14h", + JeudiSoir: "18h30 - 21h", + VendrediMidi: "11h30 - 14h", + VendrediSoir: "18h30 - 21h", + }} + /> + </div> + <Comments place={"eiffel"} /> </div> ); }