use hash router

pull/5370/head
drafish 10 months ago committed by yann300
parent 5da3d6b8f6
commit bfebda31b3
  1. 40
      apps/learneth/src/App.tsx
  2. 3
      apps/learneth/src/components/BackButton/index.tsx
  3. 104
      apps/learneth/src/pages/StepDetail/index.tsx
  4. 33
      apps/learneth/src/pages/StepList/index.tsx

@ -1,15 +1,15 @@
import React from 'react'; import React from 'react'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import {createHashRouter, RouterProvider} from 'react-router-dom'
import { ToastContainer } from 'react-toastify'; import {ToastContainer} from 'react-toastify'
import LoadingScreen from './components/LoadingScreen'; import LoadingScreen from './components/LoadingScreen'
import LogoPage from './pages/Logo'; import LogoPage from './pages/Logo'
import HomePage from './pages/Home'; import HomePage from './pages/Home'
import StepListPage from './pages/StepList'; import StepListPage from './pages/StepList'
import StepDetailPage from './pages/StepDetail'; import StepDetailPage from './pages/StepDetail'
import 'react-toastify/dist/ReactToastify.css'; import 'react-toastify/dist/ReactToastify.css'
import './App.css'; import './App.css'
export const router = createBrowserRouter([ export const router = createHashRouter([
{ {
path: '/', path: '/',
element: <LogoPage />, element: <LogoPage />,
@ -26,26 +26,16 @@ export const router = createBrowserRouter([
path: '/detail', path: '/detail',
element: <StepDetailPage />, element: <StepDetailPage />,
}, },
]); ])
function App(): JSX.Element { function App(): JSX.Element {
return ( return (
<> <>
<RouterProvider router={router} /> <RouterProvider router={router} />
<LoadingScreen /> <LoadingScreen />
<ToastContainer <ToastContainer position="bottom-right" newestOnTop closeOnClick rtl={false} pauseOnFocusLoss draggable pauseOnHover autoClose={false} theme="colored" />
position="bottom-right"
newestOnTop
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
autoClose={false}
theme="colored"
/>
</> </>
); )
} }
export default App; export default App

@ -1,5 +1,5 @@
import React, {useState} from 'react' import React, {useState} from 'react'
import {Link, useNavigate} from 'react-router-dom' import {Link, useLocation, useNavigate} from 'react-router-dom'
import {Button, Modal, Tooltip, OverlayTrigger} from 'react-bootstrap' import {Button, Modal, Tooltip, OverlayTrigger} from 'react-bootstrap'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
import {faHome, faBars, faChevronLeft, faChevronRight} from '@fortawesome/free-solid-svg-icons' import {faHome, faBars, faChevronLeft, faChevronRight} from '@fortawesome/free-solid-svg-icons'
@ -8,6 +8,7 @@ import './index.scss'
function BackButton({entity}: any) { function BackButton({entity}: any) {
const navigate = useNavigate() const navigate = useNavigate()
const location = useLocation()
const [show, setShow] = useState(false) const [show, setShow] = useState(false)
// const theme = useAppSelector((state) => state.remixide.theme) // const theme = useAppSelector((state) => state.remixide.theme)
const isDetailPage = location.pathname === '/detail' const isDetailPage = location.pathname === '/detail'

@ -1,43 +1,44 @@
import React, { useEffect } from 'react'; import React, {useEffect} from 'react'
import { useNavigate } from 'react-router-dom'; import {useLocation, useNavigate} from 'react-router-dom'
import Markdown from 'react-markdown'; import Markdown from 'react-markdown'
import rehypeRaw from 'rehype-raw'; import rehypeRaw from 'rehype-raw'
import BackButton from '../../components/BackButton'; import BackButton from '../../components/BackButton'
import { useAppSelector, useAppDispatch } from '../../redux/hooks'; import {useAppSelector, useAppDispatch} from '../../redux/hooks'
import './index.scss'; import './index.scss'
function StepDetailPage() { function StepDetailPage() {
const navigate = useNavigate(); const navigate = useNavigate()
const dispatch = useAppDispatch(); const location = useLocation()
const queryParams = new URLSearchParams(location.search); const dispatch = useAppDispatch()
const id = queryParams.get('id') as string; const queryParams = new URLSearchParams(location.search)
const stepId = Number(queryParams.get('stepId')); const id = queryParams.get('id') as string
const stepId = Number(queryParams.get('stepId'))
const { const {
workshop: { detail, selectedId }, workshop: {detail, selectedId},
remixide: { errorLoadingFile, errors, success }, remixide: {errorLoadingFile, errors, success},
} = useAppSelector((state: any) => state); } = useAppSelector((state: any) => state)
const entity = detail[selectedId].entities[id]; const entity = detail[selectedId].entities[id]
const steps = entity.steps; const steps = entity.steps
const step = steps[stepId]; const step = steps[stepId]
console.log(step); console.log(step)
useEffect(() => { useEffect(() => {
dispatch({ dispatch({
type: 'remixide/displayFile', type: 'remixide/displayFile',
payload: step, payload: step,
}); })
dispatch({ dispatch({
type: 'remixide/save', type: 'remixide/save',
payload: { errors: [], success: false }, payload: {errors: [], success: false},
}); })
window.scrollTo(0, 0); window.scrollTo(0, 0)
}, [step]); }, [step])
useEffect(() => { useEffect(() => {
if (errors.length > 0 || success) { if (errors.length > 0 || success) {
window.scrollTo(0, document.documentElement.scrollHeight); window.scrollTo(0, document.documentElement.scrollHeight)
} }
}, [errors, success]); }, [errors, success])
return ( return (
<> <>
@ -57,7 +58,7 @@ function StepDetailPage() {
dispatch({ dispatch({
type: 'remixide/displayFile', type: 'remixide/displayFile',
payload: step, payload: step,
}); })
}} }}
> >
Load the file Load the file
@ -71,9 +72,7 @@ function StepDetailPage() {
</> </>
)} )}
<div className="container-fluid"> <div className="container-fluid">
<Markdown rehypePlugins={[rehypeRaw]}> <Markdown rehypePlugins={[rehypeRaw]}>{step.markdown?.content}</Markdown>
{step.markdown?.content}
</Markdown>
</div> </div>
{step.test?.content ? ( {step.test?.content ? (
<> <>
@ -85,7 +84,7 @@ function StepDetailPage() {
dispatch({ dispatch({
type: 'remixide/displayFile', type: 'remixide/displayFile',
payload: step, payload: step,
}); })
}} }}
> >
Load the file Load the file
@ -100,7 +99,7 @@ function StepDetailPage() {
dispatch({ dispatch({
type: 'remixide/testStep', type: 'remixide/testStep',
payload: step, payload: step,
}); })
}} }}
> >
Check Answer Check Answer
@ -112,7 +111,7 @@ function StepDetailPage() {
dispatch({ dispatch({
type: 'remixide/showAnswer', type: 'remixide/showAnswer',
payload: step, payload: step,
}); })
}} }}
> >
Show answer Show answer
@ -126,11 +125,7 @@ function StepDetailPage() {
<button <button
className="nav-item rounded-0 nav-link btn btn-success test" className="nav-item rounded-0 nav-link btn btn-success test"
onClick={() => { onClick={() => {
navigate( navigate(stepId === steps.length - 1 ? `/list?id=${id}` : `/detail?id=${id}&stepId=${stepId + 1}`)
stepId === steps.length - 1
? `/list?id=${id}`
: `/detail?id=${id}&stepId=${stepId + 1}`,
);
}} }}
> >
Next Next
@ -142,7 +137,7 @@ function StepDetailPage() {
dispatch({ dispatch({
type: 'remixide/showAnswer', type: 'remixide/showAnswer',
payload: step, payload: step,
}); })
}} }}
> >
Show answer Show answer
@ -159,11 +154,7 @@ function StepDetailPage() {
<button <button
className="w-100 rounded-0 nav-item nav-link btn btn-success" className="w-100 rounded-0 nav-item nav-link btn btn-success"
onClick={() => { onClick={() => {
navigate( navigate(stepId === steps.length - 1 ? `/list?id=${id}` : `/detail?id=${id}&stepId=${stepId + 1}`)
stepId === steps.length - 1
? `/list?id=${id}`
: `/detail?id=${id}&stepId=${stepId + 1}`,
);
}} }}
> >
Next Next
@ -171,28 +162,19 @@ function StepDetailPage() {
)} )}
<div id="errors"> <div id="errors">
{success && ( {success && (
<div <div className="alert rounded-0 alert-success mb-0 mt-0" role="alert">
className="alert rounded-0 alert-success mb-0 mt-0"
role="alert"
>
Well done! No errors. Well done! No errors.
</div> </div>
)} )}
{errors.length > 0 && ( {errors.length > 0 && (
<> <>
{!success && ( {!success && (
<div <div className="alert rounded-0 alert-danger mb-0 mt-0" role="alert">
className="alert rounded-0 alert-danger mb-0 mt-0"
role="alert"
>
Errors Errors
</div> </div>
)} )}
{errors.map((error: string, index: number) => ( {errors.map((error: string, index: number) => (
<div <div key={index} className="alert rounded-0 alert-warning mb-0 mt-0">
key={index}
className="alert rounded-0 alert-warning mb-0 mt-0"
>
{error} {error}
</div> </div>
))} ))}
@ -210,7 +192,7 @@ function StepDetailPage() {
dispatch({ dispatch({
type: 'remixide/showAnswer', type: 'remixide/showAnswer',
payload: step, payload: step,
}); })
}} }}
> >
Show answer Show answer
@ -221,7 +203,7 @@ function StepDetailPage() {
<button <button
className="w-100 btn btn-success" className="w-100 btn btn-success"
onClick={() => { onClick={() => {
navigate(`/detail?id=${id}&stepId=${stepId + 1}`); navigate(`/detail?id=${id}&stepId=${stepId + 1}`)
}} }}
> >
Next Next
@ -231,7 +213,7 @@ function StepDetailPage() {
<button <button
className="w-100 btn btn-success" className="w-100 btn btn-success"
onClick={() => { onClick={() => {
navigate(`/list?id=${id}`); navigate(`/list?id=${id}`)
}} }}
> >
Finish tutorial Finish tutorial
@ -240,7 +222,7 @@ function StepDetailPage() {
</> </>
)} )}
</> </>
); )
} }
export default StepDetailPage; export default StepDetailPage

@ -1,16 +1,17 @@
import React from 'react'; import React from 'react'
import { Link } from 'react-router-dom'; import {Link, useLocation} from 'react-router-dom'
import Markdown from 'react-markdown'; import Markdown from 'react-markdown'
import BackButton from '../../components/BackButton'; import BackButton from '../../components/BackButton'
import SlideIn from '../../components/SlideIn'; import SlideIn from '../../components/SlideIn'
import { useAppSelector } from '../../redux/hooks'; import {useAppSelector} from '../../redux/hooks'
import './index.scss'; import './index.scss'
function StepListPage(): JSX.Element { function StepListPage(): JSX.Element {
const queryParams = new URLSearchParams(location.search); const location = useLocation()
const id = queryParams.get('id') as string; const queryParams = new URLSearchParams(location.search)
const { detail, selectedId } = useAppSelector((state) => state.workshop); const id = queryParams.get('id') as string
const entity = detail[selectedId].entities[id]; const {detail, selectedId} = useAppSelector((state) => state.workshop)
const entity = detail[selectedId].entities[id]
return ( return (
<> <>
@ -27,18 +28,14 @@ function StepListPage(): JSX.Element {
<SlideIn> <SlideIn>
<article className="list-group m-3"> <article className="list-group m-3">
{entity.steps.map((step: any, i: number) => ( {entity.steps.map((step: any, i: number) => (
<Link <Link key={i} to={`/detail?id=${id}&stepId=${i}`} className="rounded-0 btn btn-light border-bottom text-left steplink">
key={i}
to={`/detail?id=${id}&stepId=${i}`}
className="rounded-0 btn btn-light border-bottom text-left steplink"
>
{step.name} » {step.name} »
</Link> </Link>
))} ))}
</article> </article>
</SlideIn> </SlideIn>
</> </>
); )
} }
export default StepListPage; export default StepListPage

Loading…
Cancel
Save