Moved from next-localization to next-i18next
Removed unneeded pagesdependabot/npm_and_yarn/typescript-eslint/parser-4.33.0
parent
07e8106807
commit
04139e543d
@ -1,52 +1,9 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8
|
||||
},
|
||||
"plugins": ["prettier"],
|
||||
"ignorePatterns": ["node_modules/*", ".next/*", ".out/*", "!.prettierrc.js"],
|
||||
"extends": ["eslint:recommended"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/*.ts", "**/*.tsx"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:jsx-a11y/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"react/prop-types": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"jsx-a11y/anchor-is-valid": "off",
|
||||
"jsx-a11y/no-autofocus": "off",
|
||||
"@typescript-eslint/no-unused-vars": ["error"],
|
||||
"@typescript-eslint/explicit-function-return-type": [
|
||||
"warn",
|
||||
{
|
||||
"allowExpressions": true,
|
||||
"allowConciseArrowFunctionExpressionsStartingWithVoid": true,
|
||||
"allowTypedFunctionExpressions": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"plugins": [
|
||||
"prettier"
|
||||
],
|
||||
"extends": "next/core-web-vitals",
|
||||
"rules": {
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
}
|
@ -1,2 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
i18n: {
|
||||
locales: ['en', 'nl'],
|
||||
defaultLocale: 'en',
|
||||
},
|
||||
};
|
@ -1,6 +1,5 @@
|
||||
const { i18n } = require('./next-i18next.config');
|
||||
|
||||
module.exports = {
|
||||
i18n: {
|
||||
locales: ['en', 'nl'],
|
||||
defaultLocale: 'en',
|
||||
},
|
||||
}
|
||||
i18n,
|
||||
};
|
||||
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "Page not found",
|
||||
"description": "This page either doesn't exist or has been deleted",
|
||||
"back": "Go back"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Home",
|
||||
"description": "A simple portfolio website to display my projects.",
|
||||
"subtitle": "Hi, I am a full stack web developer",
|
||||
"projects": {
|
||||
"title": "Projects",
|
||||
"button": "Check out my projects"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"title": "Portfolio",
|
||||
"projects": "Projects",
|
||||
"contact": "Contact",
|
||||
"github": "Source code"
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "Pagina niet gevonden",
|
||||
"description": "Deze pagina bestaat niet of is verwijderd",
|
||||
"back": "Ga terug"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Thuis",
|
||||
"description": "Een simpele portfolio website om mijn projecten te bekijken.",
|
||||
"subtitle": "Hoi, Ik ben een full stack web developer",
|
||||
"projects": {
|
||||
"title": "Projecten",
|
||||
"button": "Bekijk mijn projecten"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"title": "Portfolio",
|
||||
"projects": "Projecten",
|
||||
"contact": "Contact",
|
||||
"github": "Bron code"
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow: /shifts
|
||||
Disallow:
|
@ -1,42 +0,0 @@
|
||||
@import '../styles/colors.scss';
|
||||
|
||||
.lds {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
|
||||
div {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 8px;
|
||||
border: 8px solid $text;
|
||||
border-radius: 50%;
|
||||
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||
border-color: $text transparent transparent transparent;
|
||||
|
||||
&:nth-child(1) {
|
||||
animation-delay: -0.45s;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
animation-delay: -0.3s;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
animation-delay: -0.15s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes lds-ring {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import styles from './Spinner.module.scss';
|
||||
|
||||
const Spinner: FC = () => (
|
||||
<div className={styles.lds}>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Spinner;
|
@ -1,9 +0,0 @@
|
||||
import { GetStaticProps } from 'next';
|
||||
|
||||
export const getStaticProps: GetStaticProps = async ({ locale }) => {
|
||||
const { default: lngDict = {} } = await import(`./locales/${locale}.json`);
|
||||
|
||||
return {
|
||||
props: { lngDict },
|
||||
};
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"pages": {
|
||||
"home": {
|
||||
"title": "Home",
|
||||
"description": "A simple portfolio website to display my projects.",
|
||||
"subtitle": "Hi, I am a full stack web developer",
|
||||
"projects": {
|
||||
"button": "Check out my projects"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nav": {
|
||||
"projects": "Projects",
|
||||
"contact": "Contact",
|
||||
"github": "Source code"
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"pages": {
|
||||
"home": {
|
||||
"title": "Thuis",
|
||||
"description": "Een simpele portfolio website om mijn projecten te bekijken.",
|
||||
"subtitle": "Hoi, Ik ben een full stack web developer",
|
||||
"projects": {
|
||||
"button": "Bekijk mijn projecten"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nav": {
|
||||
"projects": "Projecten",
|
||||
"contact": "Contact",
|
||||
"github": "Bron code"
|
||||
}
|
||||
}
|
@ -1,20 +1,29 @@
|
||||
import { FC } from 'react';
|
||||
import { GetStaticProps, NextPage } from 'next';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||
|
||||
import Page from '@components/Page';
|
||||
import Layout from '@components/Layout';
|
||||
import PageBuilder from '@components/PageBuilder';
|
||||
|
||||
export { getStaticProps } from '../locales';
|
||||
const NotFound: NextPage = () => {
|
||||
const { t } = useTranslation('404');
|
||||
|
||||
const NotFound: FC = () => (
|
||||
<Page title="Page not found" description="This page either doesn't exist or has been deleted">
|
||||
<Layout>
|
||||
<PageBuilder
|
||||
header="Not found"
|
||||
subtitle="This page either doesn't exist or has been deleted"
|
||||
/>
|
||||
</Layout>
|
||||
</Page>
|
||||
);
|
||||
return (
|
||||
<Page title={t('title')} description={t('description')}>
|
||||
<Layout>
|
||||
<PageBuilder button={t('back')} header={t('title')} subtitle={t('description')} />
|
||||
</Layout>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStaticProps: GetStaticProps = async ({ locale }) => {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['404', 'nav'])),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default NotFound;
|
||||
|
@ -1,28 +1,21 @@
|
||||
import { ThemeProvider } from 'next-themes';
|
||||
|
||||
import { I18nProvider } from 'next-localization';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
import type { AppProps } from 'next/app';
|
||||
|
||||
import { appWithTranslation } from 'next-i18next';
|
||||
|
||||
import 'milligram';
|
||||
|
||||
import '@styles/raleway.css';
|
||||
import '@styles/roboto.css';
|
||||
import '@styles/montserrat.css';
|
||||
|
||||
import '@styles/globals.scss';
|
||||
|
||||
const App = ({ Component, pageProps }: AppProps): JSX.Element => {
|
||||
const router = useRouter();
|
||||
const { lngDict, ...rest } = pageProps;
|
||||
|
||||
return (
|
||||
<I18nProvider lngDict={lngDict} locale={router.locale}>
|
||||
<ThemeProvider>
|
||||
<Component {...rest} />
|
||||
</ThemeProvider>
|
||||
</I18nProvider>
|
||||
<ThemeProvider>
|
||||
<Component {...pageProps} />
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
export default appWithTranslation(App);
|
||||
|
@ -1,27 +0,0 @@
|
||||
import Document, {
|
||||
Html,
|
||||
Head,
|
||||
Main,
|
||||
NextScript,
|
||||
DocumentInitialProps,
|
||||
DocumentContext,
|
||||
} from 'next/document';
|
||||
|
||||
export default class AppDocument extends Document {
|
||||
static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
|
||||
const initialProps = await Document.getInitialProps(ctx);
|
||||
return { ...initialProps };
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
.header {
|
||||
font-size: 4rem;
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
padding-top: 4rem;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
resize: none;
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.submit {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.contact {
|
||||
height: 100vh;
|
||||
|
||||
padding-top: 10rem;
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
import { NextPage } from 'next';
|
||||
import { useTheme } from 'next-themes';
|
||||
|
||||
import ReCAPTCHA from 'react-google-recaptcha';
|
||||
|
||||
import Page from '@components/Page';
|
||||
import Layout from '@components/Layout';
|
||||
|
||||
export { getStaticProps } from '../locales';
|
||||
|
||||
import styles from './contact.module.scss';
|
||||
|
||||
const formURL = 'https://forms.guusvanmeerveld.dev/portfolio';
|
||||
|
||||
const Contact: NextPage = () => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
return (
|
||||
<Page description="Contact me" title="Contact">
|
||||
<Layout>
|
||||
<div className={styles.contact}>
|
||||
<div className="container">
|
||||
<div className={styles.header} id="contact">
|
||||
Contact
|
||||
</div>
|
||||
<form
|
||||
encType="application/x-www-form-urlencoded"
|
||||
action={formURL}
|
||||
className="content"
|
||||
method="POST"
|
||||
name="contact"
|
||||
>
|
||||
<label htmlFor="email">Email</label>
|
||||
<input
|
||||
className={styles.input}
|
||||
name="email"
|
||||
type="email"
|
||||
required
|
||||
placeholder="Your email address"
|
||||
id="email"
|
||||
/>
|
||||
|
||||
<label htmlFor="type">Message type</label>
|
||||
<select className={styles.input} name="type[]" id="type">
|
||||
<option value="bug">Bug</option>
|
||||
<option value="question">Question</option>
|
||||
<option value="suggestion">Suggestion</option>
|
||||
<option value="other">Other</option>
|
||||
</select>
|
||||
|
||||
<label htmlFor="message">Message</label>
|
||||
<textarea
|
||||
className={styles.textarea}
|
||||
required
|
||||
name="message"
|
||||
placeholder="Your message"
|
||||
></textarea>
|
||||
|
||||
<ReCAPTCHA
|
||||
theme={theme as 'light' | 'dark'}
|
||||
sitekey={process.env.NEXT_PUBLIC_CAPTCHA_KEY}
|
||||
/>
|
||||
|
||||
<button className={styles.submit + ' button'} type="submit">
|
||||
Send
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default Contact;
|
@ -1,40 +0,0 @@
|
||||
.body {
|
||||
padding-top: 6rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
height: calc(100vh - 6rem);
|
||||
padding-top: 5rem;
|
||||
|
||||
text-align: center;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.table {
|
||||
background-color: var(--secondary);
|
||||
padding: 3rem;
|
||||
|
||||
font-family: 'Roboto';
|
||||
|
||||
border-radius: 7.5px;
|
||||
border: var(--borders) 1px solid;
|
||||
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tableHeader {
|
||||
font-family: 'Raleway';
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.weekDays {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error {
|
||||
button {
|
||||
margin-right: 2rem;
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
import { NextPage } from 'next';
|
||||
import Link from 'next/link';
|
||||
|
||||
import { Info, DateTime } from 'luxon';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import { FC } from 'react';
|
||||
|
||||
import { stringToTime } from '@utils/date';
|
||||
|
||||
import Spinner from '@components/Spinner';
|
||||
import Layout from '@components/Layout';
|
||||
import Page from '@components/Page';
|
||||
|
||||
import Shift from '@models/shifts';
|
||||
|
||||
export { getStaticProps } from '../locales';
|
||||
|
||||
import styles from './shifts.module.scss';
|
||||
|
||||
interface APIResponse {
|
||||
updated: Date;
|
||||
parsed: Shift[];
|
||||
}
|
||||
|
||||
const Error: FC = () => (
|
||||
<>
|
||||
<div className={styles.error}>
|
||||
<h1>Error retrieving shift information</h1>
|
||||
<button className="button">Retry</button>
|
||||
<Link href="/">
|
||||
<a>
|
||||
<button className="button">Go back</button>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const Table: FC = () => {
|
||||
const { data, error } = useSWR<APIResponse>('https://api.g-vm.nl/appie');
|
||||
|
||||
if (error) {
|
||||
return <Error />;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<>
|
||||
<Spinner />
|
||||
<h1>Retrieving shift information...</h1>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
const weeks = new Map<number, Record<string, Shift>>();
|
||||
|
||||
data.parsed.forEach((shift) => {
|
||||
const weekNumber = DateTime.fromISO(shift.start).weekNumber;
|
||||
const dayName = DateTime.fromISO(shift.start).weekdayLong;
|
||||
|
||||
const current = weeks.get(weekNumber);
|
||||
|
||||
weeks.set(weekNumber, { ...current, [dayName]: shift });
|
||||
});
|
||||
|
||||
return (
|
||||
<table className={styles.table}>
|
||||
<caption>
|
||||
<h1 className={styles.tableHeader}>Work timesheet</h1>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr className={styles.weekDays}>
|
||||
<th></th>
|
||||
{Info.weekdays().map((day) => (
|
||||
<th key={day}>{day}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Array.from(weeks).map(([weekNumber, week], i) => (
|
||||
<tr key={i}>
|
||||
<th>{weekNumber}</th>
|
||||
{Info.weekdays().map((weekDay) => {
|
||||
week[weekDay] ? (
|
||||
<td key={week[weekDay].start}>
|
||||
{stringToTime(week[weekDay].start)} - {stringToTime(week[weekDay].end)}
|
||||
</td>
|
||||
) : (
|
||||
<td></td>
|
||||
);
|
||||
})}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const Shifts: NextPage = () => (
|
||||
<Page description="Check mijn AH rooster" title="Shifts">
|
||||
<Layout>
|
||||
<div className={styles.body}>
|
||||
<div className={styles.content}>
|
||||
<div>
|
||||
<Table />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</Page>
|
||||
);
|
||||
|
||||
export default Shifts;
|
@ -1,3 +0,0 @@
|
||||
.icon {
|
||||
font-size: 10rem;
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,19 +0,0 @@
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
&:focus {
|
||||
border-color: $primary !important;
|
||||
}
|
||||
|
||||
color: $text;
|
||||
border-color: $borders !important;
|
||||
|
||||
font-family: 'Roboto';
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
select {
|
||||
&:focus {
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 8" width="30"><path fill="%23388e3c" d="M0,0l6,8l6-8"/></svg>');
|
||||
}
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Raleway';
|
||||
font-family: 'Montserrat';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(./fonts/raleway.woff2) format('woff2');
|
||||
src: url('./fonts/montserrat.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F,
|
||||
U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(./fonts/roboto.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F,
|
||||
U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
export const stringToTime = (date: string): string => DateTime.fromISO(date).toFormat('T');
|
Loading…
Reference in new issue