Refactoring to Typescript...

This commit is contained in:
2022-11-15 02:53:16 +01:00
parent 48d1b3b4ed
commit d61f17a0f3
30 changed files with 702 additions and 345 deletions
+7 -7
View File
@@ -1,14 +1,14 @@
import Router from 'preact-router'
import { route } from 'preact-router'
import { useEffect } from 'preact/hooks'
import { AdminPage } from './pages/Admin.jsx'
import { AdminPage } from './pages/Admin'
import { HomePage } from './pages/Home.jsx'
import { LoginPage } from './pages/Login.jsx'
import { ProblemPage } from './pages/Problem.jsx'
import { ProfilePage } from './pages/Profile.jsx'
import { HomePage } from './pages/Home'
import { LoginPage } from './pages/Login'
import { ProblemPage } from './pages/Problem'
import { ProfilePage } from './pages/Profile'
const Redirect = ({ to }) => {
const Redirect = ({ to }: { default: boolean; to: string }) => {
useEffect(() => {
route(to, true)
}, [])
@@ -20,7 +20,7 @@ const Redirect = ({ to }) => {
)
}
export const App = ({ url }) => {
export const App = ({ url }: { url?: string }) => {
return (
<Router url={url}>
<HomePage path="/" />
+6 -5
View File
@@ -1,8 +1,9 @@
import { Link } from 'preact-router/match'
import { isAdministrator, USER_ROLE_ADMIN, USER_ROLE_MODERATOR } from '../../shared/constants.js'
const ROLE_LABEL = {
admin: 'Admin',
moderator: 'Moderatore',
[USER_ROLE_ADMIN]: 'Admin',
[USER_ROLE_MODERATOR]: 'Moderatore',
}
export const Header = ({ user, noLogin }) => (
@@ -13,7 +14,7 @@ export const Header = ({ user, noLogin }) => (
<nav>
{user ? (
<>
{user.role !== 'student' && (
{isAdministrator(user.role) && (
<div class="nav-item">
<Link activeClassName="active" href="/admin">
Pannello Admin
@@ -22,8 +23,8 @@ export const Header = ({ user, noLogin }) => (
)}
<div class="nav-item">
<Link activeClassName="active" href="/profile">
@{user.username}
{user.role !== 'student' && <> ({ROLE_LABEL[user.role]})</>}
@{user.id}
{isAdministrator(user.role) && <> ({ROLE_LABEL[user.role]})</>}
</Link>
</div>
</>
+6 -1
View File
@@ -1,6 +1,6 @@
import { Markdown } from './Markdown.jsx'
export const Problem = ({ id, content, createdBy }) => {
export const Problem = ({ id, content, solutionsCount }) => {
return (
<div class="problem">
<div class="problem-header">
@@ -11,6 +11,11 @@ export const Problem = ({ id, content, createdBy }) => {
<div class="problem-content">
<Markdown source={content} />
</div>
{solutionsCount > 0 && (
<div class="problem-footer">
{solutionsCount} soluzion{solutionsCount === 1 ? 'e' : 'i'}
</div>
)}
</div>
)
}
+5 -1
View File
@@ -1,6 +1,10 @@
import { refToUserId } from '../../shared/db-refs.js'
import { Markdown } from './Markdown.jsx'
export const Solution = ({ userId, problemId, content }) => {
export const Solution = ({ sentBy, forProblem, content }) => {
const userId = refToUserId(sentBy)
const problemId = refToUserId(forProblem)
return (
<div class="solution">
<div class="solution-header">
-4
View File
@@ -1,4 +0,0 @@
import { hydrate } from 'preact'
import { App } from './App.jsx'
hydrate(<App />, document.body)
+4
View File
@@ -0,0 +1,4 @@
import { hydrate } from 'preact'
import { App } from './App'
// hydrate(<App />, document.body)
@@ -1,13 +1,15 @@
import renderToString from 'preact-render-to-string'
import { App } from './App.jsx'
import { MetadataContext } from './hooks.jsx'
// import { App } from './App'
import { MetadataContext } from './hooks'
export function render(url) {
import { RenderedPage } from '../shared/ssr'
export default (url: string): RenderedPage => {
const metadata = {}
const html = renderToString(
<MetadataContext.Provider value={metadata}>
<App url={url} />
{/* <App url={url} /> */}
</MetadataContext.Provider>
)
@@ -1,5 +1,6 @@
import { route } from 'preact-router'
import { useEffect, useState } from 'preact/hooks'
import { isAdministrator, isStudent } from '../../shared/constants.js'
import { server } from '../api.jsx'
import { Header } from '../components/Header.jsx'
import { MarkdownEditor } from '../components/MarkdownEditor.jsx'
@@ -27,7 +28,7 @@ export const AdminPage = ({}) => {
const [user] = useCurrentUser(user => {
if (!user) {
route('/login', true)
} else if (user.role !== 'admin' && user.role !== 'moderator') {
} else if (isStudent(user.role)) {
route('/', true)
}
})
@@ -10,6 +10,8 @@ export const HomePage = () => {
const [user] = useCurrentUser()
const [problems] = useReadResource('/api/problems', [])
console.log(problems)
return (
<main class="page-home">
<Header {...{ user }} />
@@ -13,7 +13,7 @@ export const LoginPage = () => {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username,
id: username,
}),
})
@@ -20,7 +20,7 @@ export const ProblemPage = ({ id }) => {
const sendSolution = async () => {
await server.post('/api/solution', {
problemId: id,
forProblem: id,
content: source,
})
@@ -13,7 +13,7 @@ export const ProfilePage = ({}) => {
route('/login', true)
}
setSolutions(await server.get(`/api/solutions?user=${user.username}`))
setSolutions(await server.get(`/api/solutions?user=${user.id}`))
})
const handleLogout = () => {
@@ -27,8 +27,8 @@ export const ProfilePage = ({}) => {
<Header {...{ user }} />
<div class="subtitle">Le tue soluzioni</div>
<div class="solution-list">
{solutions.map(({ problemId, content }) => (
<Solution {...{ problemId, content }} />
{solutions.map(({ forProblem, content }) => (
<Solution {...{ forProblem, content }} />
))}
</div>
<div class="subtitle">Altro</div>
+16 -9
View File
@@ -22,7 +22,7 @@ body {
font-family: 'Lato', sans-serif;
font-weight: 300;
font-size: 20px;
font-size: 18px;
line-height: 1;
}
@@ -70,7 +70,7 @@ input[type='text'] {
cursor: pointer;
font-family: 'Lato';
font-weight: 600;
font-size: 18px;
font-size: 16px;
color: #555;
border: 1px solid #c8c8c8;
@@ -102,7 +102,7 @@ input[type='text'] {
font-family: 'Lato';
font-weight: 600;
font-size: 18px;
font-size: 16px;
color: #555;
}
}
@@ -112,7 +112,7 @@ button {
font-family: 'Lato';
font-weight: 600;
font-size: 18px;
font-size: 16px;
color: #555;
border: 1px solid #c8c8c8;
@@ -199,7 +199,7 @@ $heading-scale: 1.25;
.text-body {
font-family: 'EB Garamond', serif;
font-weight: 400;
font-size: 21px;
font-size: 18px;
line-height: 1.41;
@@ -232,7 +232,7 @@ main {
gap: 2rem;
.subtitle {
font-size: 24px;
font-size: 22px;
}
}
@@ -301,6 +301,9 @@ header {
display: flex;
gap: 1rem;
height: 100%;
align-items: center;
.nav-item {
font-size: 24px;
font-weight: 300;
@@ -327,7 +330,7 @@ header {
background: #ffffff;
display: grid;
grid-template-rows: auto 1fr;
grid-template-rows: auto 1fr auto;
gap: 0.5rem;
.problem-header {
@@ -336,7 +339,7 @@ header {
gap: 0.25rem;
.problem-title {
font-size: 24px;
font-size: 22px;
font-weight: 400;
}
}
@@ -344,6 +347,10 @@ header {
.problem-content {
@extend .text-body;
}
.problem-footer {
font-size: 16px;
}
}
.solution {
@@ -420,7 +427,7 @@ header {
textarea {
font-family: 'DM Mono', monospace;
font-size: 18px;
font-size: 16px;
resize: none;
overflow-y: hidden;