diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..502895e --- /dev/null +++ b/.env.sample @@ -0,0 +1,5 @@ +NEXTAUTH_SECRET=xg2O32JwrcDRsQZZvwRO4DUQ5Jzud/DaHPsHqgTX3Kg= +#NEXTAUTH_URL=https://web.localhost +NEXTAUTH_URL=http://localhost:3000 +BACKEND_URL=CHANGE ME BACKEND_URL + diff --git a/.gitignore b/.gitignore index c87c9b3..89d74ad 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,9 @@ yarn-error.log* .pnpm-debug.log* # local env files -.env*.local +.env* +!.env.sample +!.env.example # vercel .vercel diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a680367 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +.next diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..80f62b8 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "singleQuote": true, + "semi": false, + "trailingComma": "all", + "tabWidth": 2, + "printWidth": 80 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e769a45 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "typescript.tsdk": "node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true +} \ No newline at end of file diff --git a/app/AuthProvider.tsx b/app/AuthProvider.tsx new file mode 100644 index 0000000..f02f57a --- /dev/null +++ b/app/AuthProvider.tsx @@ -0,0 +1,12 @@ +'use client' +import { Session } from 'next-auth' +import { SessionProvider } from 'next-auth/react' + +interface IAuthProviderProps { + children: React.ReactNode + session: Session | null +} + +export default function({ children, session }: IAuthProviderProps) { + return {children} +} diff --git a/app/[lng]/layout.tsx b/app/[lng]/layout.tsx new file mode 100644 index 0000000..539ff15 --- /dev/null +++ b/app/[lng]/layout.tsx @@ -0,0 +1,53 @@ +import '../globals.css' +import { Session } from 'next-auth' +import { DM_Sans } from '@next/font/google' + +import AuthProvider from '../AuthProvider' +import { languages } from '../i18n/settings' +import { useTranslation } from '../i18n' + +const dm_sans = DM_Sans({ + variable: '--font-dm-sans', + weight: ['400', '500', '700'], + subsets: ['latin', 'latin-ext'], +}) + +export async function generateStaticParams() { + return languages.map((lng) => ({ lng })) +} + +type RootLayoutProps = { + children: React.ReactNode, + params: { + lng: string + } +} + +async function getSession(cookie: string): Promise { + const response = await fetch(`${process.env.NEXTAUTH_URL}/api/auth/session`, { + headers: { cookie }, + }) + + if (!response?.ok) { + return null + } + + const session = await response.json() + return Object.keys(session).length > 0 ? session : null +} + +export default async function RootLayout({ children, params }: RootLayoutProps) { + const session = await getSession('next-auth.session-token') + const { i18n } = await useTranslation(params.lng) + + return ( + + + + + {children} + + + + ) +} diff --git a/app/[lng]/page.tsx b/app/[lng]/page.tsx new file mode 100644 index 0000000..48e4d76 --- /dev/null +++ b/app/[lng]/page.tsx @@ -0,0 +1,43 @@ +'use client' +import { use } from 'react' +import Link from 'next/link' +import { useSession } from 'next-auth/react' +import { useTranslation } from '../i18n/client' +import { languages } from '../i18n/settings' + +const Lang = ({ lng }: { lng: string }) => { + const links = languages.filter(l => l !== lng) + return <>{links.map(l => {l})} +} + + +export default function({ params }: PageProps) { + const { t } = useTranslation(params.lng, 'login', {}) + + const s = useSession() + + console.log({ s }) + + return <> +
+

{t('title')}

+

{t('subtitle')}

+ + {t('login')} + +
+ + +} diff --git a/app/globals.css b/app/globals.css index 4f18421..ac5fa49 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,8 +1,12 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + html, body { padding: 0; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + font-family: var(--font-dm-sans), -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; } diff --git a/app/i18n/client.ts b/app/i18n/client.ts new file mode 100644 index 0000000..108c105 --- /dev/null +++ b/app/i18n/client.ts @@ -0,0 +1,17 @@ +'use client' + +import i18next from 'i18next' +import { initReactI18next, useTranslation as useTranslationOrg } from 'react-i18next' +import resourcesToBackend from 'i18next-resources-to-backend' +import { getOptions } from './settings' + +// on client side the normal singleton is ok +i18next + .use(initReactI18next) + .use(resourcesToBackend((language: string, namespace: string) => import(`./locales/${language}/${namespace}.json`))) + .init(getOptions()) + +export function useTranslation(lng: string, ns: string, options: any) { + if (i18next.resolvedLanguage !== lng) i18next.changeLanguage(lng) + return useTranslationOrg(ns, options) +} diff --git a/app/i18n/index.ts b/app/i18n/index.ts new file mode 100644 index 0000000..5bebcdd --- /dev/null +++ b/app/i18n/index.ts @@ -0,0 +1,23 @@ +import { createInstance } from 'i18next' +import resourcesToBackend from 'i18next-resources-to-backend' +import { initReactI18next } from 'react-i18next/initReactI18next' +import { getOptions, fallbackLng } from './settings' + +const initI18next = async (lng: string, ns: string) => { + // on server side we create a new instance for each render, because during compilation everything seems to be executed in parallel + const i18nInstance = createInstance() + await i18nInstance + .use(initReactI18next) + .use(resourcesToBackend((language: string, namespace: string) => import(`./locales/${language}/${namespace}.json`))) + .init(getOptions(lng, ns)) + return i18nInstance +} + +export async function useTranslation(lng: string, ns = fallbackLng, options = {}) { + const i18nextInstance = await initI18next(lng, ns) + return { + // @ts-ignore + t: i18nextInstance.getFixedT(lng, ns, options.keyPrefix), + i18n: i18nextInstance + } +} diff --git a/app/i18n/locales/ar/login.json b/app/i18n/locales/ar/login.json new file mode 100644 index 0000000..8634d20 --- /dev/null +++ b/app/i18n/locales/ar/login.json @@ -0,0 +1,5 @@ +{ + "title": "هذه منطقة محذورة", + "subtitle": "يجب عليك تسجيل الدخول للاستمرار", + "login": "تسجيل الدخول" +} diff --git a/app/i18n/locales/ar/translation.json b/app/i18n/locales/ar/translation.json new file mode 100644 index 0000000..b3e9c76 --- /dev/null +++ b/app/i18n/locales/ar/translation.json @@ -0,0 +1,4 @@ + +{ + "h1": "مرحبا" +} diff --git a/app/i18n/locales/en/login.json b/app/i18n/locales/en/login.json new file mode 100644 index 0000000..8ac3eff --- /dev/null +++ b/app/i18n/locales/en/login.json @@ -0,0 +1,5 @@ +{ + "title": "This is a protected page", + "subtitle": "You need to login to continue", + "login": "login" +} diff --git a/app/i18n/locales/en/translation.json b/app/i18n/locales/en/translation.json new file mode 100644 index 0000000..d2aab47 --- /dev/null +++ b/app/i18n/locales/en/translation.json @@ -0,0 +1,3 @@ +{ + "h1": "Hello world" +} diff --git a/app/i18n/settings.ts b/app/i18n/settings.ts new file mode 100644 index 0000000..8d41209 --- /dev/null +++ b/app/i18n/settings.ts @@ -0,0 +1,17 @@ +export const fallbackLng = 'en' +export const languages = [fallbackLng, 'ar'] +export const defaultNS = 'translation' + +export function getOptions(lng = fallbackLng, ns = defaultNS) { + return { + // debug: true, + supportedLngs: languages, + // preload: languages, + fallbackLng, + lng, + fallbackNS: defaultNS, + defaultNS, + ns + } +} + diff --git a/app/layout.tsx b/app/layout.tsx deleted file mode 100644 index 245bd75..0000000 --- a/app/layout.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import './globals.css' - -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( - - {/* - will contain the components returned by the nearest parent - head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head - */} - - {children} - - ) -} diff --git a/app/layout.tsxx b/app/layout.tsxx new file mode 100644 index 0000000..bfeade3 --- /dev/null +++ b/app/layout.tsxx @@ -0,0 +1,53 @@ +import './globals.css' +import { Session } from 'next-auth' +import { DM_Sans } from '@next/font/google' + +import AuthProvider from './AuthProvider' +import { languages } from './i18n/settings' +import { useTranslation } from './i18n' + +const dm_sans = DM_Sans({ + variable: '--font-dm-sans', + weight: ['400', '500', '700'], + subsets: ['latin', 'latin-ext'], +}) + +export async function generateStaticParams() { + return languages.map((lng) => ({ lng })) +} + +type RootLayoutProps = { + children: React.ReactNode, + params: { + lng: string + } +} + +async function getSession(cookie: string): Promise { + const response = await fetch(`${process.env.NEXTAUTH_URL}/api/auth/session`, { + headers: { cookie }, + }) + + if (!response?.ok) { + return null + } + + const session = await response.json() + return Object.keys(session).length > 0 ? session : null +} + +export default async function RootLayout({ children, params }: RootLayoutProps) { + const session = await getSession('next-auth.session-token') + const { i18n } = await useTranslation(params.lng) + console.log(i18n.dir(), params.lng) + return ( + + + + + {children} + + + + ) +} diff --git a/app/page.module.css b/app/page.module.css deleted file mode 100644 index a978c99..0000000 --- a/app/page.module.css +++ /dev/null @@ -1,146 +0,0 @@ -.container { - padding: 0 2rem; -} - -.main { - min-height: 100vh; - padding: 4rem 0; - flex: 1; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -.footer { - display: flex; - flex: 1; - padding: 2rem 0; - border-top: 1px solid #eaeaea; - justify-content: center; - align-items: center; -} - -.footer a { - display: flex; - justify-content: center; - align-items: center; - flex-grow: 1; -} - -.title { - margin: 0; - line-height: 1.15; - font-size: 4rem; - font-style: normal; - font-weight: 800; - letter-spacing: -0.025em; -} - -.title a { - text-decoration: none; - color: #0070f3; -} - -.title a:hover, -.title a:focus, -.title a:active { - text-decoration: underline; -} - -.title, -.description { - text-align: center; -} - -.description { - margin: 4rem 0; - line-height: 1.5; - font-size: 1.5rem; -} - -.code { - background: #fafafa; - border-radius: 5px; - padding: 0.75rem; - font-size: 1.1rem; - font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, - Bitstream Vera Sans Mono, Courier New, monospace; -} - -.grid { - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - max-width: 1200px; -} - -.card { - margin: 1rem; - padding: 1.5rem; - text-align: left; - color: inherit; - text-decoration: none; - border: 1px solid #eaeaea; - border-radius: 10px; - transition: color 0.15s ease, border-color 0.15s ease; - max-width: 300px; -} - -.card:hover, -.card:focus, -.card:active { - color: #0070f3; - border-color: #0070f3; -} - -.card h2 { - margin: 0 0 1rem 0; - font-size: 1.5rem; -} - -.card p { - margin: 0; - font-size: 1.25rem; - line-height: 1.5; -} - -.logo { - height: 1em; - margin-left: 0.5rem; -} - -@media (max-width: 600px) { - .grid { - width: 100%; - flex-direction: column; - } -} - -@media (prefers-color-scheme: dark) { - .title { - background: linear-gradient(180deg, #ffffff 0%, #aaaaaa 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - text-fill-color: transparent; - } - .title a { - background: linear-gradient(180deg, #0070f3 0%, #0153af 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - text-fill-color: transparent; - } - .card, - .footer { - border-color: #222; - } - .code { - background: #111; - } - .logo img { - filter: invert(1); - } -} diff --git a/app/page.tsx b/app/page.tsx deleted file mode 100644 index 35bd264..0000000 --- a/app/page.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import Image from 'next/image' -import styles from './page.module.css' - -export default function Home() { - return ( -
-
-

- Welcome to Next.js 13! -

- -

- Get started by editing{' '} - app/page.tsx -

- -
- -

Documentation →

-

Find in-depth information about Next.js 13

-
- - -

Examples →

-

Explore the Next.js 13 playground.

-
- - -

Deploy →

-

Deploy your Next.js site to a public URL with Vercel.

-
-
-
- - -
- ) -} diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 0000000..1259842 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,67 @@ +import { NextRequest, NextResponse, NextMiddleware } from 'next/server' +import acceptLanguage from 'accept-language' +import { fallbackLng, languages } from './app/i18n/settings' +import { pathToRegexp } from 'path-to-regexp' + +acceptLanguage.languages(languages) + +const cookieName = 'i18next' + +export function i18nMiddleware(req: NextRequest) { + let lng + if (req.cookies.has(cookieName)) + lng = acceptLanguage.get(req.cookies.get(cookieName)?.value) + if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language')) + if (!lng) lng = fallbackLng + + if (req.nextUrl.pathname === '/') { + return NextResponse.redirect(new URL(`/${lng}`, req.url)) + } + + if (req.headers.has('referer')) { + const refererUrl = new URL(req.headers.get('referer') as string) + const lngInReferer = languages.find((l: string) => + refererUrl.pathname.startsWith(`/${l}`), + ) + const response = NextResponse.next() + if (lngInReferer) response.cookies.set(cookieName, lngInReferer) + return response + } + + return NextResponse.next() +} + +type Middleware = { + matcher: string | string[] | RegExp + handler: NextMiddleware +} + +function handlePaths(middlewares: Middleware[]): NextMiddleware { + return async function(req, ev) { + const path = req.nextUrl.pathname + const middleware = middlewares.find((m) => + pathToRegexp(m.matcher).test(path), + ) + + if (middleware) { + return middleware.handler(req, ev) + } + + // if there's no middleware just continue + return NextResponse.next() + } +} + +const DASHBOARD_URL = '/api/auth/signin?callbackUrl=%2Fdashboard' + +export const middleware: NextMiddleware = handlePaths([ + { + matcher: ['/'].concat(languages.map((l) => `/${l}/`)), + handler: (req) => i18nMiddleware(req), + }, + { + matcher: ['/sign-in', '/login'], + handler: (req: NextRequest) => + NextResponse.redirect(new URL(DASHBOARD_URL, req.url)), + }, +]) diff --git a/package.json b/package.json index ef901ff..a0cf1b1 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,25 @@ "lint": "next lint" }, "dependencies": { + "@next/font": "^13.0.6", "@types/node": "18.11.11", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", + "accept-language": "^3.0.18", + "i18next": "^22.1.4", + "i18next-resources-to-backend": "^1.1.0", + "konsta": "^1.0.2", "next": "13.0.6", + "next-auth": "^4.18.3", + "path-to-regexp": "^6.2.1", "react": "18.2.0", "react-dom": "18.2.0", + "react-i18next": "^12.1.1", "typescript": "4.9.4" + }, + "devDependencies": { + "autoprefixer": "^10.4.13", + "postcss": "^8.4.19", + "tailwindcss": "^3.2.4" } } diff --git a/pages/api/auth/[...nextauth].ts b/pages/api/auth/[...nextauth].ts new file mode 100644 index 0000000..356343e --- /dev/null +++ b/pages/api/auth/[...nextauth].ts @@ -0,0 +1,50 @@ +import NextAuth from 'next-auth' +import CredentialsProvider from 'next-auth/providers/credentials' + +const URL = process.env.BACKEND_URL + +export const authOptions = {} + +export default NextAuth({ + providers: [ + CredentialsProvider({ + name: 'Credentials', + credentials: { + email: { label: 'Email', type: 'text' }, + password: { label: 'Password', type: 'password' }, + }, + async authorize(creds, _req) { + const u = `${URL}/auth/login` + const res = await fetch(u, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + email: creds?.email, + password: creds?.password, + }), + }) + + const user = await res.json() + if (res.ok && user) { + return user + } + return null + }, + }), + ], + callbacks: { + async jwt({ token, account, user }) { + if (account) { + token.status = user?.status + token.role = user?.role + } + return token + }, + async session({ session, token }) { + session.user.status = token.status as string + session.user.role = token.role as string + return session + }, + }, +}) + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3a0f427..47640e6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,29 +1,64 @@ lockfileVersion: 5.4 specifiers: + '@next/font': ^13.0.6 '@types/node': 18.11.11 '@types/react': 18.0.26 '@types/react-dom': 18.0.9 + accept-language: ^3.0.18 + autoprefixer: ^10.4.13 + i18next: ^22.1.4 + i18next-resources-to-backend: ^1.1.0 + konsta: ^1.0.2 next: 13.0.6 + next-auth: ^4.18.3 + path-to-regexp: ^6.2.1 + postcss: ^8.4.19 react: 18.2.0 react-dom: 18.2.0 + react-i18next: ^12.1.1 + tailwindcss: ^3.2.4 typescript: 4.9.4 dependencies: + '@next/font': 13.0.6 '@types/node': 18.11.11 '@types/react': 18.0.26 '@types/react-dom': 18.0.9 + accept-language: 3.0.18 + i18next: 22.1.4 + i18next-resources-to-backend: 1.1.0 + konsta: 1.0.2 next: 13.0.6_biqbaboplfbrettd7655fr4n2y + next-auth: 4.18.3_6jx7hpii6hgsrmhxgqrmo3277u + path-to-regexp: 6.2.1 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 + react-i18next: 12.1.1_uedexzmmdjaqapw3mm5hri2poi typescript: 4.9.4 +devDependencies: + autoprefixer: 10.4.13_postcss@8.4.19 + postcss: 8.4.19 + tailwindcss: 3.2.4_postcss@8.4.19 + packages: + /@babel/runtime/7.20.6: + resolution: {integrity: sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: false + /@next/env/13.0.6: resolution: {integrity: sha512-yceT6DCHKqPRS1cAm8DHvDvK74DLIkDQdm5iV+GnIts8h0QbdHvkUIkdOvQoOODgpr6018skbmSQp12z5OWIQQ==} dev: false + /@next/font/13.0.6: + resolution: {integrity: sha512-5vxNmvnV0CbYjQGtztD5Axft9C7npKihbQpiFhnDwdb99f9K/QSFfcJqxz0E5QBkf67O2niVGJ5lApJDu78w0w==} + dev: false + /@next/swc-android-arm-eabi/13.0.6: resolution: {integrity: sha512-FGFSj3v2Bluw8fD/X+1eXIEB0PhoJE0zfutsAauRhmNpjjZshLDgoXMWm1jTRL/04K/o9gwwO2+A8+sPVCH1uw==} engines: {node: '>= 10'} @@ -141,6 +176,31 @@ packages: dev: false optional: true + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.14.0 + dev: true + + /@panva/hkdf/1.0.2: + resolution: {integrity: sha512-MSAs9t3Go7GUkMhpKC44T58DJ5KGk2vBo+h1cqQeqlMfdGkxaVB78ZWpv9gYi/g2fa4sopag9gJsNvS8XGgWJA==} + dev: false + /@swc/helpers/0.4.14: resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==} dependencies: @@ -173,22 +233,292 @@ packages: resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} dev: false + /accept-language/3.0.18: + resolution: {integrity: sha512-sUofgqBPzgfcF20sPoBYGQ1IhQLt2LSkxTnlQSuLF3n5gPEqd5AimbvOvHEi0T1kLMiGVqPWzI5a9OteBRth3A==} + dependencies: + bcp47: 1.1.2 + stable: 0.1.8 + dev: false + + /acorn-node/1.8.2: + resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==} + dependencies: + acorn: 7.4.1 + acorn-walk: 7.2.0 + xtend: 4.0.2 + dev: true + + /acorn-walk/7.2.0: + resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn/7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /anymatch/3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /arg/5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: true + + /autoprefixer/10.4.13_postcss@8.4.19: + resolution: {integrity: sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.21.4 + caniuse-lite: 1.0.30001436 + fraction.js: 4.2.0 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.19 + postcss-value-parser: 4.2.0 + dev: true + + /bcp47/1.1.2: + resolution: {integrity: sha512-JnkkL4GUpOvvanH9AZPX38CxhiLsXMBicBY2IAtqiVN8YulGDQybUydWA4W6yAMtw6iShtw+8HEF6cfrTHU+UQ==} + engines: {node: '>=0.10'} + dev: false + + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist/4.21.4: + resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001436 + electron-to-chromium: 1.4.284 + node-releases: 2.0.6 + update-browserslist-db: 1.0.10_browserslist@4.21.4 + dev: true + + /camelcase-css/2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: true + /caniuse-lite/1.0.30001436: resolution: {integrity: sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==} - dev: false + + /chokidar/3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true /client-only/0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} dev: false + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /cookie/0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /cssesc/3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + /csstype/3.1.1: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} dev: false + /defined/1.0.1: + resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} + dev: true + + /detective/5.2.1: + resolution: {integrity: sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==} + engines: {node: '>=0.8.0'} + hasBin: true + dependencies: + acorn-node: 1.8.2 + defined: 1.0.1 + minimist: 1.2.7 + dev: true + + /didyoumean/1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: true + + /dlv/1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: true + + /electron-to-chromium/1.4.284: + resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} + dev: true + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /fast-glob/3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fastq/1.14.0: + resolution: {integrity: sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==} + dependencies: + reusify: 1.0.4 + dev: true + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /fraction.js/4.2.0: + resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} + dev: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent/6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /html-parse-stringify/3.0.1: + resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} + dependencies: + void-elements: 3.1.0 + dev: false + + /i18next-resources-to-backend/1.1.0: + resolution: {integrity: sha512-h/DhIkFQ2T++MkL+cfbXBPTT9r02Pa1/2zCmbnsEWxB+dwKQYZ3lh1JQintKuK6Kn2nl7ivYJEUtzAI7fDtopw==} + dependencies: + '@babel/runtime': 7.20.6 + dev: false + + /i18next/22.1.4: + resolution: {integrity: sha512-MCDtNRyovLY22rgLoZdCzg2QIza1V1A/3Hxb99akJzTDjcqCRWEsglTpFUt0vUjOxSxz+WmxmFETLHORRS+n6Q==} + dependencies: + '@babel/runtime': 7.20.6 + dev: false + + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + dependencies: + has: 1.0.3 + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /jose/4.11.1: + resolution: {integrity: sha512-YRv4Tk/Wlug8qicwqFNFVEZSdbROCHRAC6qu/i0dyNKr5JQdoa2pIGoS04lLO/jXQX7Z9omoNewYIVIxqZBd9Q==} + dev: false + /js-tokens/4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: false + /konsta/1.0.2: + resolution: {integrity: sha512-EIi/u6HDgGy9Vbi0a2AUtsQo4qN8l1ZZWyJs/D18MjVUnVxqX7Od9O8odO+XCIzZd1djeUmxfH6frDW71UvyhQ==} + engines: {node: '>= 4.7.0'} + dev: false + + /lilconfig/2.0.6: + resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==} + engines: {node: '>=10'} + dev: true + /loose-envify/1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -196,10 +526,59 @@ packages: js-tokens: 4.0.0 dev: false + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /minimist/1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + dev: true + /nanoid/3.3.4: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + + /next-auth/4.18.3_6jx7hpii6hgsrmhxgqrmo3277u: + resolution: {integrity: sha512-oZrTPnaF7YCMm4T6+FY47+1wHacE7V6YX+MCuvRTZMca7zHAc2WPMdTED6eV3hkqp2znEdilhD4aXQ5BuCpYIw==} + engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0} + peerDependencies: + next: ^12.2.5 || ^13 + nodemailer: ^6.6.5 + react: ^17.0.2 || ^18 + react-dom: ^17.0.2 || ^18 + peerDependenciesMeta: + nodemailer: + optional: true + dependencies: + '@babel/runtime': 7.20.6 + '@panva/hkdf': 1.0.2 + cookie: 0.5.0 + jose: 4.11.1 + next: 13.0.6_biqbaboplfbrettd7655fr4n2y + oauth: 0.9.15 + openid-client: 5.3.1 + preact: 10.11.3 + preact-render-to-string: 5.2.6_preact@10.11.3 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + uuid: 8.3.2 dev: false /next/13.0.6_biqbaboplfbrettd7655fr4n2y: @@ -246,9 +625,129 @@ packages: - babel-plugin-macros dev: false + /node-releases/2.0.6: + resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-range/0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: true + + /oauth/0.9.15: + resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} + dev: false + + /object-hash/2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + dev: false + + /object-hash/3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: true + + /oidc-token-hash/5.0.1: + resolution: {integrity: sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ==} + engines: {node: ^10.13.0 || >=12.0.0} + dev: false + + /openid-client/5.3.1: + resolution: {integrity: sha512-RLfehQiHch9N6tRWNx68cicf3b1WR0x74bJWHRc25uYIbSRwjxYcTFaRnzbbpls5jroLAaB/bFIodTgA5LJMvw==} + dependencies: + jose: 4.11.1 + lru-cache: 6.0.0 + object-hash: 2.2.0 + oidc-token-hash: 5.0.1 + dev: false + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-to-regexp/6.2.1: + resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + dev: false + /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: false + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify/2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /postcss-import/14.1.0_postcss@8.4.19: + resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==} + engines: {node: '>=10.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.19 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.1 + dev: true + + /postcss-js/4.0.0_postcss@8.4.19: + resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.3.3 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.19 + dev: true + + /postcss-load-config/3.1.4_postcss@8.4.19: + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.0.6 + postcss: 8.4.19 + yaml: 1.10.2 + dev: true + + /postcss-nested/6.0.0_postcss@8.4.19: + resolution: {integrity: sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.19 + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-selector-parser/6.0.11: + resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-value-parser/4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true /postcss/8.4.14: resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} @@ -259,6 +758,41 @@ packages: source-map-js: 1.0.2 dev: false + /postcss/8.4.19: + resolution: {integrity: sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /preact-render-to-string/5.2.6_preact@10.11.3: + resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} + peerDependencies: + preact: '>=10' + dependencies: + preact: 10.11.3 + pretty-format: 3.8.0 + dev: false + + /preact/10.11.3: + resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} + dev: false + + /pretty-format/3.8.0: + resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} + dev: false + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru/5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + /react-dom/18.2.0_react@18.2.0: resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: @@ -269,6 +803,26 @@ packages: scheduler: 0.23.0 dev: false + /react-i18next/12.1.1_uedexzmmdjaqapw3mm5hri2poi: + resolution: {integrity: sha512-mFdieOI0LDy84q3JuZU6Aou1DoWW2fhapcTGeBS8+vWSJuViuoCLQAMYSb0QoHhXS8B0WKUOPpx4cffAP7r/aA==} + peerDependencies: + i18next: '>= 19.0.0' + react: '>= 16.8.0' + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + '@babel/runtime': 7.20.6 + html-parse-stringify: 3.0.1 + i18next: 22.1.4 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + /react/18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} @@ -276,6 +830,43 @@ packages: loose-envify: 1.4.0 dev: false + /read-cache/1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: true + + /readdirp/3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /regenerator-runtime/0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: false + + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.11.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + /scheduler/0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: @@ -285,6 +876,10 @@ packages: /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + + /stable/0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' dev: false /styled-jsx/5.1.0_react@18.2.0: @@ -304,6 +899,52 @@ packages: react: 18.2.0 dev: false + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /tailwindcss/3.2.4_postcss@8.4.19: + resolution: {integrity: sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==} + engines: {node: '>=12.13.0'} + hasBin: true + peerDependencies: + postcss: ^8.0.9 + dependencies: + arg: 5.0.2 + chokidar: 3.5.3 + color-name: 1.1.4 + detective: 5.2.1 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.2.12 + glob-parent: 6.0.2 + is-glob: 4.0.3 + lilconfig: 2.0.6 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.19 + postcss-import: 14.1.0_postcss@8.4.19 + postcss-js: 4.0.0_postcss@8.4.19 + postcss-load-config: 3.1.4_postcss@8.4.19 + postcss-nested: 6.0.0_postcss@8.4.19 + postcss-selector-parser: 6.0.11 + postcss-value-parser: 4.2.0 + quick-lru: 5.1.1 + resolve: 1.22.1 + transitivePeerDependencies: + - ts-node + dev: true + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + /tslib/2.4.1: resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} dev: false @@ -313,3 +954,42 @@ packages: engines: {node: '>=4.2.0'} hasBin: true dev: false + + /update-browserslist-db/1.0.10_browserslist@4.21.4: + resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.4 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /uuid/8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: false + + /void-elements/3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + dev: false + + /xtend/4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /yaml/1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: true diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..33ad091 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..c346501 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,14 @@ +const konstaConfig = require('konsta/config') + +/** @type {import('tailwindcss').Config} */ +module.exports = konstaConfig({ + content: [ + "./app/**/*.{js,ts,jsx,tsx}", // Note the addition of the `app` directory. + "./pages/**/*.{js,ts,jsx,tsx}", + "./components/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], +}) diff --git a/types/next-auth.d.ts b/types/next-auth.d.ts new file mode 100644 index 0000000..77b25bb --- /dev/null +++ b/types/next-auth.d.ts @@ -0,0 +1,29 @@ +import NextAuth, { DefaultSession } from 'next-auth' + +declare module 'next-auth' { + /** + * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context + */ + interface Session { + user: { + firstName: string + lastName: string + // role: 'OWNER' | 'SCHOOL' | 'TEACHER' | 'PARENT' + // status: 'ACTIVE' | 'INACTIVE' + role: string + status: string + } & DefaultSession['user'] + } + interface AdapterUser extends User { + id: string + email: string + emailVerified: Date | null + role: string + } + interface User { + role: string + status: string + firstName: string + lastName: string + } +} diff --git a/types/page.d.ts b/types/page.d.ts new file mode 100644 index 0000000..e823743 --- /dev/null +++ b/types/page.d.ts @@ -0,0 +1,12 @@ +type RootLayoutProps = { + children: React.ReactNode, + params: { + lng: string + } +} + +type PageProps = { + params: { + lng: string + } +}