mirror of
https://git.roussel.pro/telecom-paris/pact.git
synced 2026-02-09 10:30:17 +01:00
ajout de composants pour li'nterface admin
This commit is contained in:
56
code/interface_admin/components/Avis.jsx
Normal file
56
code/interface_admin/components/Avis.jsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Card, Col, Row, Table } from 'react-bootstrap';
|
||||||
|
import { BsPersonFill } from 'react-icons/bs';
|
||||||
|
import styles from '../styles/Avis.module.css'
|
||||||
|
|
||||||
|
export default function Avis({ age, sex, text, date, grade, gradeOther }) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<Card.Title>Avis</Card.Title>
|
||||||
|
<Card.Body>
|
||||||
|
<Row>
|
||||||
|
<h2>Auteur</h2>
|
||||||
|
<Col xs={1}>
|
||||||
|
<BsPersonFill className={styles.personIcon} />
|
||||||
|
</Col>
|
||||||
|
<Col className='d-flex flex-column'>
|
||||||
|
<p>Age : {age}</p>
|
||||||
|
<p>Sexe : {sex}</p>
|
||||||
|
<p>Date de publication : {date}</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<h2>Notes</h2>
|
||||||
|
<Table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Critère</th>
|
||||||
|
<th>Note</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Général</td>
|
||||||
|
<td>{grade} / 10</td>
|
||||||
|
</tr>
|
||||||
|
{gradeOther.map(({ title, grade }) => {
|
||||||
|
return <tr key={title}>
|
||||||
|
<td>{title}</td>
|
||||||
|
<td>{grade}/10</td>
|
||||||
|
</tr>
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Card>
|
||||||
|
<Card.Header>Commentaire</Card.Header>
|
||||||
|
<Card.Body>
|
||||||
|
{text}
|
||||||
|
</Card.Body>
|
||||||
|
</Card>
|
||||||
|
</Row>
|
||||||
|
</Card.Body>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
32
code/interface_admin/components/AvisList.jsx
Normal file
32
code/interface_admin/components/AvisList.jsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import React from 'react'
|
||||||
|
import { Table } from 'react-bootstrap'
|
||||||
|
import styles from '../styles/AvisList.module.css'
|
||||||
|
|
||||||
|
export default function AvisList({ avis }) {
|
||||||
|
const router = useRouter();
|
||||||
|
function handleClick(id) {
|
||||||
|
router.push(`/avis/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Note globale</th>
|
||||||
|
<th>Commentaire</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{avis.map(({ id, grade, comment, date }) => {
|
||||||
|
return <tr onClick={() => handleClick(id)} key={id} className={styles.row}>
|
||||||
|
<td>{date}</td>
|
||||||
|
<td>{grade} / 10</td>
|
||||||
|
<td>{comment}</td>
|
||||||
|
</tr>
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -2,16 +2,16 @@ import React from 'react'
|
|||||||
import { Bar } from 'react-chartjs-2'
|
import { Bar } from 'react-chartjs-2'
|
||||||
import Chart from 'chart.js/auto';
|
import Chart from 'chart.js/auto';
|
||||||
|
|
||||||
export default function ComparativeBarChart({ xlabels, data0, label0, data1, label1, title }) {
|
export default function ComparativeBarChart({ xlabels, data0, label0, data1, label1}) {
|
||||||
return (
|
return (
|
||||||
<Bar
|
<Bar
|
||||||
options={{
|
options={{
|
||||||
plugins: {
|
// plugins: {
|
||||||
title: {
|
// title: {
|
||||||
display: true,
|
// display: true,
|
||||||
text: title
|
// text: title
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
responsive: true,
|
responsive: true,
|
||||||
interaction: {
|
interaction: {
|
||||||
intersect: false,
|
intersect: false,
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import React from 'react'
|
||||||
|
import Avis from '../../components/Avis';
|
||||||
|
export default function AvisPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const {id} = router.query;
|
||||||
|
return (
|
||||||
|
<Avis age={20} sex={"f"} text={"dfjlkmksgflkgsjmdf"} grade={9} date={"2023-10-12 12:34"} gradeOther={[{title: "Propreté", grade: 8},{title: "Lorem ipsum", grade: 8}]}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
66
code/interface_admin/pages/avis/index.js
Normal file
66
code/interface_admin/pages/avis/index.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { Card, Container, Form, Row, Table } from 'react-bootstrap'
|
||||||
|
import AvisList from '../../components/AvisList';
|
||||||
|
import styles from '../../styles/AvisListPage.module.css'
|
||||||
|
|
||||||
|
export default function AvisListPage() {
|
||||||
|
const [minGrade, setMinGrade] = useState(0);
|
||||||
|
const [maxGrade, setMaxGrade] = useState(10);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(minGrade > maxGrade) {
|
||||||
|
setMinGrade(maxGrade);
|
||||||
|
}
|
||||||
|
}, [maxGrade]);
|
||||||
|
useEffect(() => {
|
||||||
|
if(minGrade > maxGrade) {
|
||||||
|
setMaxGrade(minGrade);
|
||||||
|
}
|
||||||
|
}, [minGrade])
|
||||||
|
|
||||||
|
const [avis, setAvis] = useState([
|
||||||
|
{ id: 0, date: "2023-02-11", grade: 10, comment: "lorem ipsum lorem ipsum" },
|
||||||
|
{ id: 1, date: "2023-02-11", grade: 10, comment: "Lorem ipsum lorem ipsum" },
|
||||||
|
{ id: 2, date: "2023-02-11", grade: 10, comment: "Lorem ipsum lorem ipsum" },
|
||||||
|
{ id: 3, date: "2023-02-11", grade: 10, comment: "Lorem ipsum lorem ipsum" }
|
||||||
|
])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container fluid>
|
||||||
|
<Card>
|
||||||
|
<Card.Header>Tous les avis</Card.Header>
|
||||||
|
<Card.Body>
|
||||||
|
<Row>
|
||||||
|
<Form>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label>Types d'avis</Form.Label>
|
||||||
|
<Form.Check
|
||||||
|
type="switch"
|
||||||
|
label="Automatique"
|
||||||
|
/>
|
||||||
|
<Form.Check
|
||||||
|
type="switch"
|
||||||
|
label="Manuel"
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label>Note</Form.Label>
|
||||||
|
<div className='d-flex flex-row justify-content-around col-md-6'>
|
||||||
|
<div>Min : {minGrade}/10</div>
|
||||||
|
<div className={styles.sliderContainer}>
|
||||||
|
<input type="range" value={minGrade} onChange={(e) => setMinGrade(e.target.value)} min="0" max="10" step="1" className={styles.slider}></input>
|
||||||
|
<input type="range" value={maxGrade} onChange={(e) => setMaxGrade(e.target.value)} min="0" max="10" step="1" className={styles.slider}></input>
|
||||||
|
</div>
|
||||||
|
<div>Max : {maxGrade}/10</div>
|
||||||
|
</div>
|
||||||
|
</Form.Group>
|
||||||
|
</Form>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<AvisList avis={avis} />
|
||||||
|
</Row>
|
||||||
|
</Card.Body>
|
||||||
|
</Card>
|
||||||
|
</Container >
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,14 +1,58 @@
|
|||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import { Inter } from '@next/font/google'
|
|
||||||
import { Card, Container } from 'react-bootstrap'
|
import { Card, Container } from 'react-bootstrap'
|
||||||
import ComparativeBarChart from '../components/ComparativeBarChart'
|
import ComparativeBarChart from '../components/ComparativeBarChart'
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
import styles from "../styles/Home.module.css"
|
||||||
|
|
||||||
const inter = Inter({ subsets: ['latin'] })
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [datasets, setDatasets] = useState([[1, 2, 3, 4, 5, 6, 7], [7, 6, 5, 4, 3, 2, 1]]);
|
const [datasets, setDatasets] = useState([
|
||||||
|
]);
|
||||||
|
const [averages, setAverages] = useState([]);
|
||||||
|
const [differences, setDifferences] = useState([]);
|
||||||
|
useEffect(() => {
|
||||||
|
let newAverages = []
|
||||||
|
let newDifferences = []
|
||||||
|
for (let i = 0; i < datasets.length; i++) {
|
||||||
|
newAverages[i] = datasets[i].current.reduce((a, b) => a + b) / datasets[i].current.length
|
||||||
|
newDifferences[i] = newAverages[i] - datasets[i].previous.reduce((a, b) => a + b) / datasets[i].previous.length
|
||||||
|
}
|
||||||
|
setAverages(newAverages);
|
||||||
|
setDifferences(newDifferences);
|
||||||
|
}, [datasets]);
|
||||||
|
|
||||||
|
useEffect(() => setDatasets([
|
||||||
|
{ title: "Nombre d'avis", current: [3, 2, 3, 4, 5, 6, 7], previous: [7, 6, 5, 4, 3, 2, 1] },
|
||||||
|
{ title: "Notes moyennes", current: [1, 2, 3, 4, 5, 6, 7], previous: [7, 6, 5, 4, 3, 2, 1] }
|
||||||
|
]), []);
|
||||||
|
function dataVisualizer(title, current, previous, average, difference) {
|
||||||
|
return <>
|
||||||
|
<h3>{title}</h3>
|
||||||
|
<Card className={styles.averageCard}>
|
||||||
|
<Card.Title>Moyenne</Card.Title>
|
||||||
|
<Card.Body className={styles.averageCardBody}>
|
||||||
|
<div
|
||||||
|
className={styles.averageMainValue}
|
||||||
|
>
|
||||||
|
{Math.round(average*1e2)/1e2}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={[styles.averageCardSecondaryValue, difference >= 0 ? styles.averagePositive : styles.averageNegative].join(' ')}
|
||||||
|
>
|
||||||
|
{(difference >= 0 ? "+" : "-") + Math.round(difference*1e2)/1e2}
|
||||||
|
</div>
|
||||||
|
</Card.Body>
|
||||||
|
</Card>
|
||||||
|
<ComparativeBarChart
|
||||||
|
xlabels={["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]}
|
||||||
|
label0="Cette semaine"
|
||||||
|
label1="La semaine dernière"
|
||||||
|
data0={current}
|
||||||
|
data1={previous}
|
||||||
|
/>
|
||||||
|
<hr />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -18,26 +62,11 @@ export default function Home() {
|
|||||||
</Head>
|
</Head>
|
||||||
<Container fluid>
|
<Container fluid>
|
||||||
<Card>
|
<Card>
|
||||||
<Card.Header as="h2">Vos performances de cette semaine</Card.Header>
|
<Card.Header as="h2">Vos performances cette semaine</Card.Header>
|
||||||
<div className='col col-12 col-lg-8 mx-auto'>
|
<Card.Body>
|
||||||
<Card.Body className='w-100'>
|
{datasets.map((set, i) => dataVisualizer(set.title, set.current, set.previous, averages[i], differences[i]))}
|
||||||
<ComparativeBarChart
|
|
||||||
xlabels={["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]}
|
|
||||||
label0="Cette semaine"
|
|
||||||
label1="La semaine dernière"
|
|
||||||
title="Note moyenne"
|
|
||||||
data0={datasets[0]}
|
|
||||||
data1={datasets[1]}
|
|
||||||
/>
|
|
||||||
<ComparativeBarChart
|
|
||||||
xlabels={["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]}
|
|
||||||
label0="Cette semaine"
|
|
||||||
label1="La semaine dernière"
|
|
||||||
title="Nombre d'avis"
|
|
||||||
data0={datasets[0]}
|
|
||||||
data1={datasets[1]}
|
|
||||||
/>
|
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
|
<div className='col col-12 col-lg-8 mx-auto'>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
5
code/interface_admin/styles/Avis.module.css
Normal file
5
code/interface_admin/styles/Avis.module.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.personIcon {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* font-size: 50px; */
|
||||||
|
}
|
||||||
6
code/interface_admin/styles/AvisList.module.css
Normal file
6
code/interface_admin/styles/AvisList.module.css
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
/* ==== TABLEAU ==== */
|
||||||
|
.row:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #EEE;
|
||||||
|
}
|
||||||
57
code/interface_admin/styles/AvisListPage.module.css
Normal file
57
code/interface_admin/styles/AvisListPage.module.css
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* ==== SLIDER ==== */
|
||||||
|
.sliderContainer {
|
||||||
|
position: relative;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliderContainer > input[type=range]::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
pointer-events: all;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 0 1px #C6C6C6;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliderContainer > input[type=range]::-moz-range-thumb {
|
||||||
|
z-index: 99;
|
||||||
|
pointer-events: all;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 0 1px #C6C6C6;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliderContainer > input[type=range]::-webkit-slider-thumb:hover {
|
||||||
|
background: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliderContainer >input[type=range]::-webkit-slider-thumb:active {
|
||||||
|
box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;
|
||||||
|
-webkit-box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;
|
||||||
|
}
|
||||||
|
.sliderContainer > input[type=range]::-moz-range-thumb:hover {
|
||||||
|
background: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliderContainer >input[type=range]::-moz-range-thumb:active {
|
||||||
|
box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;
|
||||||
|
-webkit-box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliderContainer >input[type="range"] {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
height: 2px;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
background-color: #C6C6C6;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +1,29 @@
|
|||||||
.graphContainer {
|
.averageCard {
|
||||||
padding: 30px 0;
|
width: min-content;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.averageCardBody {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.averageMainValue {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.averageSecondaryValue {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.averagePositive {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.averageNegative {
|
||||||
|
color: red;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user