commit
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"extends": "next/core-web-vitals"
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
.yarn/install-state.gz
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 4,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"bracketSameLine": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
# or
|
||||||
|
pnpm dev
|
||||||
|
# or
|
||||||
|
bun dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|
||||||
|
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
output: 'export',
|
||||||
|
distDir: 'out',
|
||||||
|
sassOptions: {
|
||||||
|
includePaths: [path.join(__dirname, 'styles')],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = nextConfig;
|
||||||
Generated
+6551
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "forum",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^10.16.15",
|
||||||
|
"next": "14.0.3",
|
||||||
|
"react": "^18",
|
||||||
|
"react-country-flag": "^3.1.0",
|
||||||
|
"react-dom": "^18",
|
||||||
|
"sass": "^1.69.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20",
|
||||||
|
"@types/react": "^18",
|
||||||
|
"@types/react-dom": "^18",
|
||||||
|
"eslint": "^8",
|
||||||
|
"eslint-config-next": "14.0.3",
|
||||||
|
"typescript": "^5"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 321 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 493 KiB |
@@ -0,0 +1,7 @@
|
|||||||
|
.main {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Metadata } from 'next';
|
||||||
|
import { openGraphMetadata } from '@/app/_helpers/shared_metadata';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import styles from './page.module.scss';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: '',
|
||||||
|
openGraph: {
|
||||||
|
...openGraphMetadata,
|
||||||
|
title: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<main className={styles.main}>
|
||||||
|
<div className={styles.content}></div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
.footer {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
padding: 64px 32px;
|
||||||
|
background-color: var(--dark-gray);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 1400px;
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 0 20px;
|
||||||
|
|
||||||
|
@media screen and (min-width: 1024px) {
|
||||||
|
grid-template-columns: repeat(10, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info,
|
||||||
|
.spacer,
|
||||||
|
.routeSection {
|
||||||
|
margin-bottom: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
grid-column: span 3;
|
||||||
|
h4 {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: var(--white);
|
||||||
|
margin-top: 32px;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
margin-top: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.div {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.routeSection {
|
||||||
|
grid-column: span 2;
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
color: var(--brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
margin-top: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
hr {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
border-color: var(--brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 0.6rem;
|
||||||
|
font-weight: normal;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Metadata } from 'next';
|
||||||
|
import { openGraphMetadata } from '@/app/_helpers/shared_metadata';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import styles from './footer.module.scss';
|
||||||
|
import { usePathname } from 'next/navigation';
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
const pathname: string = usePathname().substring(1);
|
||||||
|
var username: string = '';
|
||||||
|
|
||||||
|
if (pathname === 'register' || pathname === 'login') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<footer className={styles.footer}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<div className={styles.grid}>
|
||||||
|
<div className={styles.info}>
|
||||||
|
<h4>
|
||||||
|
<Link href={`/`}>Forum name</Link>
|
||||||
|
</h4>
|
||||||
|
<p>Where curiosity thrives and knowledge grows.</p>
|
||||||
|
<p>Share on</p>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.spacer}></div>
|
||||||
|
<div className={styles.routeSection}>
|
||||||
|
<h5>Links</h5>
|
||||||
|
<Link href={'/browse'}>Browse categories</Link>
|
||||||
|
<Link href={'/create'}>Create posts</Link>
|
||||||
|
<Link href={'/account'}>My account</Link>
|
||||||
|
</div>
|
||||||
|
<div className={styles.routeSection}>
|
||||||
|
<h5>Forum name</h5>
|
||||||
|
<Link href={'/contact'}>Contact</Link>
|
||||||
|
<Link href={'/about'}>About</Link>
|
||||||
|
<Link href={'/helpcenter'}>Helpcenter</Link>
|
||||||
|
</div>
|
||||||
|
<div className={styles.routeSection}>
|
||||||
|
<h5>Policies</h5>
|
||||||
|
<Link href={'/terms'}>Terms of Service</Link>
|
||||||
|
<Link href={'/privacy'}>Privacy Policy</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.copyright}>
|
||||||
|
<hr />
|
||||||
|
<p>© {new Date().getFullYear()} forumname.nl. All rights reserved.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
.header {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1001;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
padding: 0px 32px;
|
||||||
|
background: linear-gradient(0, #0000, var(--almost-black));
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin: auto;
|
||||||
|
max-width: 1400px;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
line-height: 50px;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 600px) {
|
||||||
|
.sessionuser,
|
||||||
|
.sessionbuttons {
|
||||||
|
display: inherit !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionuser,
|
||||||
|
.sessionbuttons {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionuser {
|
||||||
|
float: right;
|
||||||
|
transition: all 250ms;
|
||||||
|
margin-right: -16px;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
padding: 16px;
|
||||||
|
padding-top: 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--white);
|
||||||
|
|
||||||
|
.username {
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
transition: color 250ms;
|
||||||
|
line-height: 34px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: right;
|
||||||
|
text-transform: capitalize;
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '\25be';
|
||||||
|
float: right;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown {
|
||||||
|
transition: opacity 250ms;
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8px;
|
||||||
|
text-align: right;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionbuttons {
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
.register,
|
||||||
|
.login {
|
||||||
|
transition: all 250ms ease;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-left: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 128px;
|
||||||
|
|
||||||
|
line-height: 34px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.register {
|
||||||
|
background-color: var(--brand);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: color-mix(
|
||||||
|
in srgb,
|
||||||
|
var(--brand),
|
||||||
|
#000 15%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login {
|
||||||
|
border: 2px solid var(--brand);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border: 2px solid color-mix(in srgb, var(--brand), #000 15%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import styles from './header.module.scss';
|
||||||
|
import Sessiondata from './sessiondata';
|
||||||
|
|
||||||
|
export default function Header() {
|
||||||
|
return (
|
||||||
|
<header className={styles.header}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<h4>
|
||||||
|
<Link href={`/`}>Forum name</Link>
|
||||||
|
</h4>
|
||||||
|
{/* <nav className={styles.nav}>
|
||||||
|
<p>
|
||||||
|
<Link href={`/`}></Link>
|
||||||
|
</p>
|
||||||
|
</nav> */}
|
||||||
|
<Sessiondata />
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import styles from './header.module.scss';
|
||||||
|
import { usePathname } from 'next/navigation';
|
||||||
|
import { setSession } from '../_helpers/auth';
|
||||||
|
|
||||||
|
export default function Sessiondata() {
|
||||||
|
const pathname: string = usePathname().substring(1);
|
||||||
|
|
||||||
|
var username: string = localStorage.getItem('username') || '';
|
||||||
|
|
||||||
|
if (pathname === 'register' || pathname === 'login') {
|
||||||
|
return null;
|
||||||
|
} else if (username) {
|
||||||
|
return (
|
||||||
|
<div className={styles.sessionuser}>
|
||||||
|
<p className={styles.username}>{username}</p>
|
||||||
|
<div className={styles.dropdown}>
|
||||||
|
<Link href={'/'}>My account</Link>
|
||||||
|
<Link href={'/'} onClick={() => setSession(false)}>Logout</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div className={styles.sessionbuttons}>
|
||||||
|
<Link href={'/register'} className={styles.register}>
|
||||||
|
Sign up
|
||||||
|
</Link>
|
||||||
|
<Link href={'/login'} className={styles.login}>
|
||||||
|
Login
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
'use client';
|
||||||
|
import { Inter } from 'next/font/google';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { useSearchParams } from 'next/navigation';
|
||||||
|
const inter = Inter({ subsets: ['latin'] });
|
||||||
|
|
||||||
|
export function LoginForm() {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
var redirUrl = searchParams.get('redir');
|
||||||
|
|
||||||
|
if (localStorage.getItem('username')) {
|
||||||
|
window.location.href = '/account';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form action={() => {}} onSubmit={() => handleLogin(redirUrl)}>
|
||||||
|
<label htmlFor="username">Username</label>
|
||||||
|
<input
|
||||||
|
id="username"
|
||||||
|
type="text"
|
||||||
|
required
|
||||||
|
className={inter.className}
|
||||||
|
></input>
|
||||||
|
<label htmlFor="password">Password</label>
|
||||||
|
<input
|
||||||
|
id="password"
|
||||||
|
type="password"
|
||||||
|
required
|
||||||
|
className={inter.className}
|
||||||
|
></input>
|
||||||
|
<span id="errorMessage"></span>
|
||||||
|
<button type="submit" className={inter.className}>
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RegisterForm() {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
var redirUrl = searchParams.get('redir');
|
||||||
|
|
||||||
|
if (localStorage.getItem('username')) {
|
||||||
|
window.location.href = '/account';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form action={() => {}} onSubmit={() => handleRegister(redirUrl)}>
|
||||||
|
<label htmlFor="email">Email</label>
|
||||||
|
<input id="email" type="email" required></input>
|
||||||
|
<label htmlFor="username">Username</label>
|
||||||
|
<input id="username" type="text" required></input>
|
||||||
|
<label htmlFor="password">Password</label>
|
||||||
|
<input id="password" type="password" minLength={5} required></input>
|
||||||
|
<input id="consent" type="checkbox" required />
|
||||||
|
<label htmlFor="consent">
|
||||||
|
I have read and agree to Quiztimes'{' '}
|
||||||
|
<Link href={'/terms'}>Terms of Service</Link>
|
||||||
|
</label>
|
||||||
|
<button type="submit" className={inter.className}>
|
||||||
|
Sign up
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLogin(redirUrl: string | null) {
|
||||||
|
var data = {
|
||||||
|
username: (document.getElementById('username') as HTMLInputElement)
|
||||||
|
.value,
|
||||||
|
password: (document.getElementById('password') as HTMLInputElement)
|
||||||
|
.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch('https://quiztimes.nl/api/login', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
loginAndRedirect();
|
||||||
|
} else {
|
||||||
|
// display error message
|
||||||
|
(
|
||||||
|
document.getElementById('errorMessage') as HTMLSpanElement
|
||||||
|
).innerHTML = 'Incorrect username or password';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const loginAndRedirect = async () => {
|
||||||
|
// start session
|
||||||
|
await setSession(true);
|
||||||
|
|
||||||
|
// redirect if set
|
||||||
|
if (redirUrl !== null) {
|
||||||
|
window.location.href = redirUrl;
|
||||||
|
} else {
|
||||||
|
window.location.href = '/account';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleRegister(redirUrl: string | null) {
|
||||||
|
var data = {
|
||||||
|
username: (document.getElementById('username') as HTMLInputElement)
|
||||||
|
.value,
|
||||||
|
email: (document.getElementById('email') as HTMLInputElement).value,
|
||||||
|
password: (document.getElementById('password') as HTMLInputElement)
|
||||||
|
.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch('https://quiztimes.nl/api/register', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
loginAndRedirect();
|
||||||
|
} else {
|
||||||
|
// display error message
|
||||||
|
(
|
||||||
|
document.getElementById('errorMessage') as HTMLSpanElement
|
||||||
|
).innerHTML = 'An error occurred';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const loginAndRedirect = async () => {
|
||||||
|
// start session
|
||||||
|
await setSession(true);
|
||||||
|
|
||||||
|
// redirect if set
|
||||||
|
if (redirUrl !== null) {
|
||||||
|
window.location.href = redirUrl;
|
||||||
|
} else {
|
||||||
|
window.location.href = '/account';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setSession(setLoggedIn: boolean) {
|
||||||
|
console.log('test');
|
||||||
|
if (setLoggedIn) {
|
||||||
|
await fetch('https://quiztimes.nl/api/jwt').then((data) => {
|
||||||
|
console.log(data);
|
||||||
|
localStorage.setItem('username', 'Vincent');
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
localStorage.clear();
|
||||||
|
window.location.href = '/';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
export const openGraphMetadata = {
|
||||||
|
title: 'Quiztimes',
|
||||||
|
description: 'Quiztimes. Free Learning, Forever.',
|
||||||
|
url: 'https://quiztimes.nl',
|
||||||
|
siteName: 'Quiztimes',
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: '/og.png',
|
||||||
|
width: 1200,
|
||||||
|
height: 630,
|
||||||
|
alt: 'The quiztimes logo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/og-twitter.png',
|
||||||
|
width: 1024,
|
||||||
|
height: 512,
|
||||||
|
alt: 'The quiztimes logo',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
locale: 'en_UK',
|
||||||
|
type: 'website',
|
||||||
|
};
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,46 @@
|
|||||||
|
import '@/styles/root.scss';
|
||||||
|
import '@/styles/reset.scss';
|
||||||
|
import type { Metadata, Viewport } from 'next';
|
||||||
|
import { Inter } from 'next/font/google';
|
||||||
|
import Header from './_components/header';
|
||||||
|
import Footer from './_components/footer';
|
||||||
|
import { openGraphMetadata } from '@/app/_helpers/shared_metadata';
|
||||||
|
|
||||||
|
const inter = Inter({ subsets: ['latin'] });
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
metadataBase: new URL('https://Forum.nl'),
|
||||||
|
title: {
|
||||||
|
template: '%s | Forum',
|
||||||
|
default: 'Forum',
|
||||||
|
},
|
||||||
|
description: 'Asking questions, finding answers. talk about anything and everything.',
|
||||||
|
keywords: ['forum', 'questions', 'answers', 'knowledge'],
|
||||||
|
authors: [
|
||||||
|
{ name: 'Kaj van Schalkwijk', url: 'https://gitea.quiztimes.nl/kajvans' },
|
||||||
|
{ name: 'Ruben jimmink', url: 'https://gitea.quiztimes.nl/kajvans' },
|
||||||
|
],
|
||||||
|
openGraph: {
|
||||||
|
...openGraphMetadata,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const viewport: Viewport = {
|
||||||
|
themeColor: '#646CFF'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<body className={inter.className}>
|
||||||
|
<Header />
|
||||||
|
{children}
|
||||||
|
<Footer />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
.main {
|
||||||
|
padding-top: 0;
|
||||||
|
padding: 0 32px;
|
||||||
|
height: 100vh;
|
||||||
|
background: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
var(--almost-black) 0%,
|
||||||
|
var(--dark-gray) 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 500px;
|
||||||
|
padding: 32px;
|
||||||
|
background-color: var(--white);
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-top: 32px;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
transition: border 250ms;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
margin-top: 8px;
|
||||||
|
border: 2px solid var(--black);
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
outline: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
padding: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
border: 2px solid var(--brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
transition: background-color 250ms;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
margin-top: 32px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
outline: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
background-color: var(--brand);
|
||||||
|
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: color-mix(in srgb, var(--brand), #000 15%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
display: block;
|
||||||
|
margin-top: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--black);
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: -16px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Metadata } from 'next';
|
||||||
|
import { openGraphMetadata } from '@/app/_helpers/shared_metadata';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import styles from './page.module.scss';
|
||||||
|
import { LoginForm } from '@/app/_helpers/auth';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Login',
|
||||||
|
openGraph: {
|
||||||
|
...openGraphMetadata,
|
||||||
|
title: 'Login',
|
||||||
|
url: 'https://quiztimes.nl/login',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<main className={styles.main}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<h1>Welcome back!</h1>
|
||||||
|
<LoginForm />
|
||||||
|
<p>
|
||||||
|
Don't have an account?{' '}
|
||||||
|
<Link href="register">Sign up</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
@use '@/styles/buttons';
|
||||||
|
|
||||||
|
.main {
|
||||||
|
padding-top: 0;
|
||||||
|
padding: 0 32px;
|
||||||
|
height: 100vh;
|
||||||
|
background: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
var(--almost-black) 0%,
|
||||||
|
var(--dark-gray) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
margin: auto;
|
||||||
|
width: fit-content;
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
text-align: center;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 32px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, a {
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-top: 16px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
&:first-of-type {
|
||||||
|
@include buttons.button;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-top: 64px;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Metadata } from 'next';
|
||||||
|
import { openGraphMetadata } from '@/app/_helpers/shared_metadata';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import styles from './not-found.module.scss';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Page not found',
|
||||||
|
openGraph: {
|
||||||
|
...openGraphMetadata,
|
||||||
|
title: 'Page not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function NotFound() {
|
||||||
|
return (
|
||||||
|
<main className={styles.main}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<h1>Whoops! Looks like this page went on strike.</h1>
|
||||||
|
<h2>It's either not available or doesn't exist at all</h2>
|
||||||
|
<Link href={'/'}>Go Home</Link>
|
||||||
|
{/* <p>Or</p>
|
||||||
|
<Link href={'/helpcenter'}>Visit the Helpcenter</Link>
|
||||||
|
<Link></Link> */}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@use '@/styles/buttons';
|
||||||
|
|
||||||
|
.main {
|
||||||
|
padding-top: 5rem;
|
||||||
|
padding-left: 5rem;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Image from 'next/image';
|
||||||
|
import styles from './page.module.scss';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
const [selectedTheme, setSelectedTheme] = useState('black');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className={styles.main}>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
.main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { Metadata } from 'next';
|
||||||
|
import { openGraphMetadata } from '@/app/_helpers/shared_metadata';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import styles from './page.module.scss';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Privacy Policy',
|
||||||
|
openGraph: {
|
||||||
|
...openGraphMetadata,
|
||||||
|
title: 'Privacy Policy',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<main className={styles.main}>
|
||||||
|
<article className={styles.content}>
|
||||||
|
<h1>Privacy Policy</h1>
|
||||||
|
<p>Last updated: [insert date]</p>
|
||||||
|
<p>
|
||||||
|
<strong>Forum</strong> (<strong>"we"</strong>{' '}
|
||||||
|
or <strong>"us"</strong>) is committed to
|
||||||
|
protecting the information of their users.
|
||||||
|
</p>
|
||||||
|
<h2>Information We Collect</h2>
|
||||||
|
<ol>
|
||||||
|
<li></li>
|
||||||
|
</ol>
|
||||||
|
</article>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
.main {
|
||||||
|
padding-top: 0;
|
||||||
|
padding: 0 32px;
|
||||||
|
height: 100vh;
|
||||||
|
background: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
var(--almost-black) 0%,
|
||||||
|
var(--dark-gray) 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 500px;
|
||||||
|
padding: 32px;
|
||||||
|
background-color: var(--white);
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-top: 32px;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
label[for='consent'] {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
transition: border 250ms;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
margin-top: 8px;
|
||||||
|
border: 2px solid var(--black);
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
outline: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
padding: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
border: 2px solid var(--brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='checkbox'] {
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
transition: background-color 250ms;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
margin-top: 32px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
outline: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
background-color: var(--brand);
|
||||||
|
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: color-mix(in srgb, var(--brand), #000 15%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
display: block;
|
||||||
|
margin-top: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--black);
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Metadata } from 'next';
|
||||||
|
import { openGraphMetadata } from '@/app/_helpers/shared_metadata';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import styles from './page.module.scss';
|
||||||
|
import { Inter } from 'next/font/google';
|
||||||
|
import { RegisterForm } from '../_helpers/auth';
|
||||||
|
|
||||||
|
const inter = Inter({ subsets: ['latin'] });
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Create an account',
|
||||||
|
openGraph: {
|
||||||
|
...openGraphMetadata,
|
||||||
|
title: 'Create an account',
|
||||||
|
url: 'https://quiztimes.nl/register',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<main className={styles.main}>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<h1>Create an account</h1>
|
||||||
|
<RegisterForm />
|
||||||
|
<p>
|
||||||
|
Already have an account? <Link href="login">Log in</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
@mixin fly-in($distance: 50px) {
|
||||||
|
@keyframes fly-in {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY($distance);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
@mixin button($theme: var(--brand)) {
|
||||||
|
display: inline-block;
|
||||||
|
transition: background-color 250ms ease;
|
||||||
|
|
||||||
|
border: 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
background-color: $theme;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: color-mix(in srgb, $theme, #000 15%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:visited {
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
@use "sass:meta";
|
||||||
|
@use "./themes/lightmode";
|
||||||
|
@use "./themes/darkmode";
|
||||||
|
|
||||||
|
$colors: (
|
||||||
|
brand: hsl(237, 100%, 70%),
|
||||||
|
white: hsl(0, 0%, 100%),
|
||||||
|
off-white: hsl(0, 0%, 96%),
|
||||||
|
gray: hsl(0, 0%, 50%),
|
||||||
|
dark-gray: hsl(0, 0%, 14%),
|
||||||
|
almost-black: hsl(0, 5%, 7%),
|
||||||
|
black: hsl(0, 0%, 0%),
|
||||||
|
red: hsl(350, 74%, 45%),
|
||||||
|
green: hsl(149, 100%, 32%),
|
||||||
|
cozy: hsl(39, 32%, 84%),
|
||||||
|
);
|
||||||
|
|
||||||
|
:root {
|
||||||
|
@each $name, $value in $colors {
|
||||||
|
--#{$name}: #{$value};
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
@each $name, $value in meta.module-variables("lightmode") {
|
||||||
|
--#{$name}: #{$value};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
@each $name, $value in meta.module-variables("darkmode") {
|
||||||
|
--#{$name}: #{$value};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/* http://meyerweb.com/eric/tools/css/reset/
|
||||||
|
v2.0 | 20110126
|
||||||
|
License: none (public domain)
|
||||||
|
*/
|
||||||
|
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
div,
|
||||||
|
span,
|
||||||
|
applet,
|
||||||
|
object,
|
||||||
|
iframe,
|
||||||
|
dialog,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
p,
|
||||||
|
blockquote,
|
||||||
|
pre,
|
||||||
|
a,
|
||||||
|
abbr,
|
||||||
|
acronym,
|
||||||
|
address,
|
||||||
|
big,
|
||||||
|
cite,
|
||||||
|
code,
|
||||||
|
del,
|
||||||
|
dfn,
|
||||||
|
em,
|
||||||
|
img,
|
||||||
|
ins,
|
||||||
|
kbd,
|
||||||
|
q,
|
||||||
|
s,
|
||||||
|
samp,
|
||||||
|
small,
|
||||||
|
strike,
|
||||||
|
strong,
|
||||||
|
sub,
|
||||||
|
sup,
|
||||||
|
tt,
|
||||||
|
var,
|
||||||
|
b,
|
||||||
|
u,
|
||||||
|
i,
|
||||||
|
center,
|
||||||
|
dl,
|
||||||
|
dt,
|
||||||
|
dd,
|
||||||
|
ol,
|
||||||
|
ul,
|
||||||
|
li,
|
||||||
|
fieldset,
|
||||||
|
form,
|
||||||
|
label,
|
||||||
|
legend,
|
||||||
|
table,
|
||||||
|
caption,
|
||||||
|
tbody,
|
||||||
|
tfoot,
|
||||||
|
thead,
|
||||||
|
tr,
|
||||||
|
th,
|
||||||
|
td,
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
canvas,
|
||||||
|
details,
|
||||||
|
embed,
|
||||||
|
figure,
|
||||||
|
figcaption,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
hgroup,
|
||||||
|
menu,
|
||||||
|
nav,
|
||||||
|
output,
|
||||||
|
ruby,
|
||||||
|
section,
|
||||||
|
summary,
|
||||||
|
time,
|
||||||
|
mark,
|
||||||
|
audio,
|
||||||
|
video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
/* HTML5 display-role reset for older browsers */
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
details,
|
||||||
|
figcaption,
|
||||||
|
figure,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
hgroup,
|
||||||
|
menu,
|
||||||
|
nav,
|
||||||
|
section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
// ol,
|
||||||
|
// ul {
|
||||||
|
// list-style: none;
|
||||||
|
// }
|
||||||
|
// blockquote,
|
||||||
|
// q {
|
||||||
|
// quotes: none;
|
||||||
|
// }
|
||||||
|
blockquote:before,
|
||||||
|
blockquote:after,
|
||||||
|
q:before,
|
||||||
|
q:after {
|
||||||
|
content: "";
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
@use 'colors';
|
||||||
|
|
||||||
|
body {
|
||||||
|
width: 100vw;
|
||||||
|
background-color: var(--background);
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
color: var(--text);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
overscroll-behavior-y: none;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding-top: 50px;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
@page {
|
||||||
|
size: A4; /* DIN A4 standard, Europe */
|
||||||
|
margin: 12.7mm;
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
width: 210mm;
|
||||||
|
/* height: 297mm; */
|
||||||
|
height: 282mm;
|
||||||
|
font-size: 11px;
|
||||||
|
background: #fff;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
padding-top: 15mm;
|
||||||
|
}
|
||||||
|
header,
|
||||||
|
footer,
|
||||||
|
aside,
|
||||||
|
nav,
|
||||||
|
form {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
$text: var(--white);
|
||||||
|
$text-secondary: var(--off-white);
|
||||||
|
$background: var(--almost-black);
|
||||||
|
$background-secondary: var(--dark-gray);
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
$text: var(--black);
|
||||||
|
$text-secondary: var(--gray);
|
||||||
|
$background: var(--white);
|
||||||
|
$background-secondary: var(--off-white);
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
"out/types/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user