📦 NEW: Ajout de chronometerTimer
This commit is contained in:
parent
b21d410a88
commit
075d455fbd
3
.github/backup.sql
vendored
3
.github/backup.sql
vendored
@ -20,4 +20,5 @@ INSERT INTO `functions` (`id`, `title`, `slug`, `description`, `image`, `type`,
|
|||||||
(11, 'Heap\'s algorithm', 'heapAlgorithm', 'Génère toutes les permutations uniques possibles d\'une chaîne de caractère.', '/images/functions/heapAlgorithm.png', 'form', NULL, '[{\"name\": \"string\", \"type\": \"text\", \"label\": \"Entrez un mot :\", \"placeholder\": \"(e.g : Mot)\"}]', 1, '2019-10-11 00:01:00', '2020-04-22 23:06:15', 2),
|
(11, 'Heap\'s algorithm', 'heapAlgorithm', 'Génère toutes les permutations uniques possibles d\'une chaîne de caractère.', '/images/functions/heapAlgorithm.png', 'form', NULL, '[{\"name\": \"string\", \"type\": \"text\", \"label\": \"Entrez un mot :\", \"placeholder\": \"(e.g : Mot)\"}]', 1, '2019-10-11 00:01:00', '2020-04-22 23:06:15', 2),
|
||||||
(12, 'Raccourcisseurs de liens', 'linkShortener', 'Une URL trop longue ? Raccourcissez-là !', '/images/functions/linkShortener.png', 'form', NULL, '[{\"name\": \"url\", \"type\": \"text\", \"label\": \"Entrez le lien à raccourcir :\", \"placeholder\": \"(e.g : https://divlo.fr)\"}, {\"name\": \"shortcutName\", \"type\": \"text\", \"label\": \"Entrez le nom du raccourci :\", \"placeholder\": \"(e.g : divlo)\"}]', 1, '2019-12-11 00:00:00', '2020-04-27 16:31:38', 1),
|
(12, 'Raccourcisseurs de liens', 'linkShortener', 'Une URL trop longue ? Raccourcissez-là !', '/images/functions/linkShortener.png', 'form', NULL, '[{\"name\": \"url\", \"type\": \"text\", \"label\": \"Entrez le lien à raccourcir :\", \"placeholder\": \"(e.g : https://divlo.fr)\"}, {\"name\": \"shortcutName\", \"type\": \"text\", \"label\": \"Entrez le nom du raccourci :\", \"placeholder\": \"(e.g : divlo)\"}]', 1, '2019-12-11 00:00:00', '2020-04-27 16:31:38', 1),
|
||||||
(13, 'Liste de choses à faire', 'toDoList', 'Prévoyez la liste de choses que vous devez faire.', '/images/functions/toDoList.png', 'page', NULL, NULL, 1, '2019-12-26 00:00:00', '2020-04-27 16:34:34', 1),
|
(13, 'Liste de choses à faire', 'toDoList', 'Prévoyez la liste de choses que vous devez faire.', '/images/functions/toDoList.png', 'page', NULL, NULL, 1, '2019-12-26 00:00:00', '2020-04-27 16:34:34', 1),
|
||||||
(14, 'Juste Prix', 'rightPrice', 'Arriverez-vous à deviner le prix d\'un objet ?', '/images/functions/rightPrice.png', 'page', NULL, NULL, 1, '2020-04-27 20:17:05', '2020-04-27 21:59:22', 3);
|
(14, 'Juste Prix', 'rightPrice', 'Arriverez-vous à deviner le prix d\'un objet ?', '/images/functions/rightPrice.png', 'page', NULL, NULL, 1, '2020-04-27 20:17:05', '2020-04-27 21:59:22', 3),
|
||||||
|
(15, 'Chronomètre', 'chronometerTimer', 'Gérer votre temps facilement (et adopter la technique Pomodoro).', '/images/functions/chronometerTimer.png', 'page', NULL, NULL, 1, '2020-04-29 09:28:08', '2020-04-29 09:45:29', 1);
|
8
website/package-lock.json
generated
8
website/package-lock.json
generated
@ -8594,6 +8594,14 @@
|
|||||||
"prop-types": "^15.6.2"
|
"prop-types": "^15.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-codepen-embed": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-codepen-embed/-/react-codepen-embed-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-Lqi9uNimI4s8pGpCNU/NuP/UFscFSdgeYXfLLJym8NmzzyUt5Gbwwbkvzfp5UYj24S31eW1eClewhe5W+STULA==",
|
||||||
|
"requires": {
|
||||||
|
"prop-types": "^15.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-color": {
|
"react-color": {
|
||||||
"version": "2.18.0",
|
"version": "2.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-color/-/react-color-2.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-color/-/react-color-2.18.0.tgz",
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
"notyf": "^3.6.0",
|
"notyf": "^3.6.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"react": "16.13.0",
|
"react": "16.13.0",
|
||||||
|
"react-codepen-embed": "^1.0.1",
|
||||||
"react-color": "^2.18.0",
|
"react-color": "^2.18.0",
|
||||||
"react-datepicker": "^2.14.1",
|
"react-datepicker": "^2.14.1",
|
||||||
"react-dom": "16.13.0",
|
"react-dom": "16.13.0",
|
||||||
|
126
website/pages/functions/chronometerTimer.js
Normal file
126
website/pages/functions/chronometerTimer.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import Codepen from "react-codepen-embed";
|
||||||
|
import redirect from '../../utils/redirect';
|
||||||
|
import FunctionPage from '../../components/FunctionPage/FunctionPage';
|
||||||
|
import FunctionTabs from '../../components/FunctionPage/FunctionTabs';
|
||||||
|
import FunctionArticle from '../../components/FunctionPage/FunctionArticle';
|
||||||
|
import FunctionComments from '../../components/FunctionPage/FunctionComments/FunctionComments';
|
||||||
|
import Loader from '../../components/Loader';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { faPlay, faPause, faSync } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import api from '../../utils/api';
|
||||||
|
import '../../public/css/pages/FunctionComponent.css';
|
||||||
|
import '../../components/FunctionCard/FunctionCard.css';
|
||||||
|
import '../../public/css/pages/functions/chronometerTimer.css';
|
||||||
|
|
||||||
|
let interval;
|
||||||
|
function convertSeconds(seconds) {
|
||||||
|
return {
|
||||||
|
minutes: Math.floor(seconds / 60),
|
||||||
|
seconds: seconds % 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Chronometer = () => {
|
||||||
|
|
||||||
|
const [timeLength, setTimeLength] = useState(0); // seconds
|
||||||
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
|
|
||||||
|
const handlePlayPause = () => {
|
||||||
|
if (isPlaying) {
|
||||||
|
clearInterval(interval);
|
||||||
|
} else {
|
||||||
|
if (interval) clearInterval(interval);
|
||||||
|
interval = setInterval(() => {
|
||||||
|
setTimeLength((time) => time + 1);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
setIsPlaying(!isPlaying);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
if (interval) clearInterval(interval);
|
||||||
|
setIsPlaying(false);
|
||||||
|
setTimeLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFormattedValue = () => {
|
||||||
|
const minutesAndSeconds = convertSeconds(timeLength);
|
||||||
|
const minutes = (minutesAndSeconds.minutes < 100) ? (('0'+minutesAndSeconds.minutes).slice(-2)) : minutesAndSeconds.minutes;
|
||||||
|
const seconds = ('0'+minutesAndSeconds.seconds).slice(-2);
|
||||||
|
return `${minutes}:${seconds}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="row justify-content-center">
|
||||||
|
<div className="col-sm-24 col-md-12">
|
||||||
|
<div className="Chronometer__container">
|
||||||
|
<div className="Chronometer__item">
|
||||||
|
<div className="Chronomter__row">
|
||||||
|
<div className="Chronometer__time-left">
|
||||||
|
{/* 25:00 */}
|
||||||
|
{getFormattedValue()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="Chronometer__item Chronometer__buttons">
|
||||||
|
<div className="Chronomter__row Chronometer__row-button">
|
||||||
|
<button onClick={handlePlayPause} className="Chronometer-btn">
|
||||||
|
<FontAwesomeIcon { ...(isPlaying) ? { icon: faPause } : { icon: faPlay } } />
|
||||||
|
</button>
|
||||||
|
<button onClick={handleReset} className="Chronometer-btn" title="Remettre à zéro ?">
|
||||||
|
<FontAwesomeIcon icon={faSync} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Pomodoro = () => {
|
||||||
|
return (
|
||||||
|
<div style={{ marginBottom: '50px' }} className="container-fluid">
|
||||||
|
<Codepen hash="vYEbPoB" user="Divlo" height={800} defaultTab="result" preview={false} loader={() => <Loader />} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const FunctionTabManager = (props) => {
|
||||||
|
return (
|
||||||
|
<FunctionTabs setSlideIndex={props.setSlideIndex} slideIndex={props.slideIndex}>
|
||||||
|
<div className="FunctionComponent__slide">
|
||||||
|
<Chronometer />
|
||||||
|
</div>
|
||||||
|
<div className="FunctionComponent__slide">
|
||||||
|
<Pomodoro />
|
||||||
|
</div>
|
||||||
|
<div className="FunctionComponent__slide">
|
||||||
|
<FunctionArticle article={props.article} />
|
||||||
|
</div>
|
||||||
|
<div className="FunctionComponent__slide">
|
||||||
|
<FunctionComments functionId={props.id} />
|
||||||
|
</div>
|
||||||
|
</FunctionTabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const chronometerTimer = (props) => (
|
||||||
|
<FunctionPage
|
||||||
|
FunctionTabManager={FunctionTabManager}
|
||||||
|
{ ...props }
|
||||||
|
tabNames={["⏰ Chronomètre", "⌛ Pomodoro", "📝 Article", "📬 Commentaires"]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export async function getServerSideProps(context) {
|
||||||
|
return api.get(`/functions/chronometerTimer`)
|
||||||
|
.then((response) => ({ props: response.data }))
|
||||||
|
.catch(() => redirect(context, '/404'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default chronometerTimer;
|
@ -7,7 +7,6 @@ import FunctionComments from '../../components/FunctionPage/FunctionComments/Fun
|
|||||||
import Loader from '../../components/Loader';
|
import Loader from '../../components/Loader';
|
||||||
import api from '../../utils/api';
|
import api from '../../utils/api';
|
||||||
import '../../public/css/pages/FunctionComponent.css';
|
import '../../public/css/pages/FunctionComponent.css';
|
||||||
import '../../public/css/pages/functions/toDoList.css';
|
|
||||||
import '../../components/FunctionCard/FunctionCard.css';
|
import '../../components/FunctionCard/FunctionCard.css';
|
||||||
import '../../public/css/pages/functions/rightPrice.css';
|
import '../../public/css/pages/functions/rightPrice.css';
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ import FunctionArticle from '../../components/FunctionPage/FunctionArticle';
|
|||||||
import FunctionComments from '../../components/FunctionPage/FunctionComments/FunctionComments';
|
import FunctionComments from '../../components/FunctionPage/FunctionComments/FunctionComments';
|
||||||
import api from '../../utils/api';
|
import api from '../../utils/api';
|
||||||
import '../../public/css/pages/FunctionComponent.css';
|
import '../../public/css/pages/FunctionComponent.css';
|
||||||
import '../../public/css/pages/functions/toDoList.css';
|
|
||||||
import '../../components/FunctionCard/FunctionCard.css';
|
import '../../components/FunctionCard/FunctionCard.css';
|
||||||
|
import '../../public/css/pages/functions/toDoList.css';
|
||||||
|
|
||||||
const ManageToDo = () => {
|
const ManageToDo = () => {
|
||||||
|
|
||||||
|
38
website/public/css/pages/functions/chronometerTimer.css
Normal file
38
website/public/css/pages/functions/chronometerTimer.css
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
.Chronometer__container {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
box-shadow: 0px 0px 6px 6px rgba(0, 0, 0, .25);
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 1rem;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
.Chronometer__item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.Chronomter__row {
|
||||||
|
margin: 8px 0 16px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.Chronometer__time-left {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.Chronometer__buttons {
|
||||||
|
border-top: solid 3px var(--important);
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
.Chronometer__row-button {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.Chronometer-btn {
|
||||||
|
color: var(--text-color);
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
margin-left: 14px;
|
||||||
|
margin-right: 14px;
|
||||||
|
width: 2em;
|
||||||
|
}
|
Reference in New Issue
Block a user