Replace UI module with Next.js
This commit is contained in:
parent
8aeff18162
commit
616205fe73
91 changed files with 3570 additions and 722 deletions
|
@ -1,66 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import React, { FC } from 'react';
|
||||
import { Route, Switch } from 'wouter';
|
||||
|
||||
import { useAuth } from '@procyon/auth/hook/useAuth';
|
||||
import Section from '@procyon/components/Section';
|
||||
import { Skeleton } from '@procyon/components/Skeleton';
|
||||
import { MenuItem } from '@procyon/components/Skeleton/types';
|
||||
|
||||
import { WelcomePage } from 'pages/WelcomePage';
|
||||
|
||||
import { buildRoute, Routes } from './routes';
|
||||
|
||||
const topMenu: MenuItem[][] = [
|
||||
[
|
||||
{ label: 'Routa', href: buildRoute('root') },
|
||||
],
|
||||
[
|
||||
// authenticated
|
||||
],
|
||||
];
|
||||
|
||||
const userMenu: MenuItem[][] = [
|
||||
[
|
||||
// public
|
||||
],
|
||||
[
|
||||
// authenticated
|
||||
],
|
||||
];
|
||||
|
||||
export const App: FC = () => {
|
||||
const { authenticated } = useAuth();
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
items={{
|
||||
logo: <>Many</>,
|
||||
top: authenticated ? topMenu[1] : topMenu[0],
|
||||
user: authenticated ? userMenu[1] : userMenu[0],
|
||||
}}
|
||||
components={{
|
||||
footer: (
|
||||
<div className="text-center footer">
|
||||
<Section>
|
||||
Tento web používá pouze technické cookie. Monitorování návštěvnosti je zcela anonymní a je prováděno na straně
|
||||
provozovatele webu.
|
||||
</Section>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
>
|
||||
{authenticated ? (
|
||||
<Switch>
|
||||
<Route>404!</Route>
|
||||
</Switch>
|
||||
) : (
|
||||
<Switch>
|
||||
<Route path={Routes.root} component={WelcomePage} />
|
||||
<Route>404!</Route>
|
||||
</Switch>
|
||||
)}
|
||||
</Skeleton>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="https://fonts.googleapis.com/css?family=Ubuntu:400,700&subset=cyrillic-ext" rel="stylesheet">
|
||||
<title>$(AppName)</title>
|
||||
<meta name="robots" content="index,follow">
|
||||
|
||||
<style>
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #666;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
|
||||
<% if (htmlWebpackPlugin.options.env.websiteId) { %>
|
||||
<script async src="https://wa.romanjaros.dev/script.js"
|
||||
data-website-id="<%= htmlWebpackPlugin.options.env.websiteId %>">
|
||||
</script>
|
||||
<% } %>
|
||||
|
||||
</html>
|
28
source/ui/src/app/layout.tsx
Normal file
28
source/ui/src/app/layout.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
// @ts-nocheck
|
||||
import '../styles/global.css';
|
||||
|
||||
import type { Metadata } from 'next';
|
||||
import { Poppins } from 'next/font/google';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { ReduxProvider } from '../providers/Redux';
|
||||
import { SkeletonProvider } from '../providers/Skeleton';
|
||||
|
||||
const inter = Poppins({ weight: ['300', '500', '700'], display: 'swap', subsets: ['latin'] });
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: `$(AppName)`,
|
||||
description: '',
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: Readonly<{ children: ReactNode }>) {
|
||||
return (
|
||||
<ReduxProvider>
|
||||
<html lang="en">
|
||||
<body className={inter.className}>
|
||||
<SkeletonProvider>{children}</SkeletonProvider>
|
||||
</body>
|
||||
</html>
|
||||
</ReduxProvider>
|
||||
);
|
||||
}
|
4
source/ui/src/app/next-page/page.tsx
Normal file
4
source/ui/src/app/next-page/page.tsx
Normal file
|
@ -0,0 +1,4 @@
|
|||
// @ts-nocheck
|
||||
export default function Page() {
|
||||
return <b>Next page</b>;
|
||||
}
|
4
source/ui/src/app/page.tsx
Normal file
4
source/ui/src/app/page.tsx
Normal file
|
@ -0,0 +1,4 @@
|
|||
// @ts-nocheck
|
||||
export default function Page() {
|
||||
return <>Welcome!</>;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import { DotNestedKeys } from '@procyon/localization/types';
|
||||
|
||||
export const Routes = {
|
||||
root: '/'
|
||||
};
|
||||
|
||||
export const buildRoute = (route: DotNestedKeys<typeof Routes>) => {
|
||||
let path = '';
|
||||
let obj: Record<string, any> = Routes;
|
||||
route.split('.').forEach((key: any) => {
|
||||
path += obj[key]?.base ?? obj[key];
|
||||
obj = obj[key];
|
||||
});
|
||||
return path;
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
// @ts-nocheck
|
||||
// import generated apis
|
||||
|
||||
import { AnyAction, combineReducers, configureStore, ThunkDispatch } from '@reduxjs/toolkit';
|
||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import authReducer from '@procyon/auth/slice';
|
||||
import { AUTH_REDUCER_NAME } from '@procyon/auth/types';
|
||||
import { ROOT_REDUCER_NAME } from '@procyon/constants/redux';
|
||||
|
||||
import { emptyApi } from '../api/emptyApi';
|
||||
|
||||
type procyonReducer = {
|
||||
[AUTH_REDUCER_NAME]: typeof authReducer;
|
||||
};
|
||||
|
||||
const store = configureStore({
|
||||
reducer: {
|
||||
[ROOT_REDUCER_NAME]: combineReducers<procyonReducer>({
|
||||
[AUTH_REDUCER_NAME]: authReducer,
|
||||
}),
|
||||
[emptyApi.reducerPath]: emptyApi.reducer,
|
||||
},
|
||||
middleware: (gDM) => [...gDM({ serializableCheck: false }).concat([emptyApi.middleware])],
|
||||
devTools: process.env.NODE_ENV === 'development'
|
||||
});
|
||||
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
export type AppDispatch = ThunkDispatch<RootState, unknown, AnyAction>;
|
||||
|
||||
export const useAppDispatch: () => AppDispatch = useDispatch;
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||
|
||||
export default store;
|
|
@ -1,25 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import 'types/global';
|
||||
import 'localization/locale';
|
||||
import 'utils/yup';
|
||||
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import { ModalWrapper } from '@procyon/components/Modal/context';
|
||||
import { ToasterWrapper } from '@procyon/components/Toaster/context';
|
||||
|
||||
import { App } from './app/app';
|
||||
import store from './app/store';
|
||||
|
||||
render(
|
||||
<Provider store={store}>
|
||||
<ModalWrapper>
|
||||
<ToasterWrapper>
|
||||
<App />
|
||||
</ToasterWrapper>
|
||||
</ModalWrapper>
|
||||
</Provider>,
|
||||
document.getElementById('app')
|
||||
);
|
|
@ -1,6 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
|
||||
export const WelcomePage = () => {
|
||||
return <div className="welcome">Seedling app generator.</div>;
|
||||
};
|
16
source/ui/src/providers/Redux.tsx
Normal file
16
source/ui/src/providers/Redux.tsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
// @ts-nocheck
|
||||
'use client';
|
||||
|
||||
import { useRef, ReactNode } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import { makeStore } from '../redux/store';
|
||||
|
||||
export function ReduxProvider({ children }: { children: ReactNode }) {
|
||||
const storeRef = useRef<ReturnType<typeof makeStore> | null>(null);
|
||||
if (!storeRef.current) {
|
||||
storeRef.current = makeStore();
|
||||
}
|
||||
|
||||
return <Provider store={storeRef.current}>{children}</Provider>;
|
||||
}
|
28
source/ui/src/providers/Skeleton.tsx
Normal file
28
source/ui/src/providers/Skeleton.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
// @ts-nocheck
|
||||
'use client';
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Skeleton } from '@procyon/components/Skeleton';
|
||||
|
||||
export function SkeletonProvider({ children }: Readonly<{ children: React.ReactNode }>) {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<Skeleton
|
||||
onHref={(path) => router.push(path as string)}
|
||||
items={{
|
||||
logo: <>App</>,
|
||||
top: [
|
||||
{
|
||||
label: 'Home',
|
||||
href: '/',
|
||||
},
|
||||
{
|
||||
label: 'Next page',
|
||||
href: '/next-page',
|
||||
},
|
||||
],
|
||||
}}>
|
||||
{children}
|
||||
</Skeleton>
|
||||
);
|
||||
}
|
27
source/ui/src/redux/store.ts
Normal file
27
source/ui/src/redux/store.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
// @ts-nocheck
|
||||
import { combineReducers, configureStore } from '@reduxjs/toolkit';
|
||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import authReducer from '@procyon/auth/slice';
|
||||
|
||||
import { emptyApi } from './emptyApi';
|
||||
|
||||
export const makeStore = () =>
|
||||
configureStore({
|
||||
reducer: {
|
||||
procyon: combineReducers({
|
||||
auth: authReducer,
|
||||
}),
|
||||
[emptyApi.reducerPath]: emptyApi.reducer,
|
||||
},
|
||||
middleware: (gDM) => gDM().prepend(emptyApi.middleware),
|
||||
devTools: process.env.NODE_ENV === 'development',
|
||||
});
|
||||
|
||||
export type ReduxStore = ReturnType<typeof makeStore>;
|
||||
|
||||
export type RootState = ReturnType<ReduxStore['getState']>;
|
||||
export type AppDispatch = ReduxStore['dispatch'];
|
||||
|
||||
export const useAppDispatch: () => AppDispatch = useDispatch;
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
|
@ -1,8 +0,0 @@
|
|||
const component = () => ({
|
||||
});
|
||||
|
||||
module.exports = ({ addComponents, theme }) => {
|
||||
addComponents(component(theme));
|
||||
};
|
||||
|
||||
module.exports.component = component;
|
9
source/ui/src/styles/components/component.ts
Normal file
9
source/ui/src/styles/components/component.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { PluginCreator } from 'tailwindcss/types/config';
|
||||
|
||||
const component = () => ({});
|
||||
|
||||
const creator: PluginCreator = ({ addComponents, theme }) => {
|
||||
addComponents({});
|
||||
};
|
||||
|
||||
export default creator;
|
|
@ -1,9 +1,5 @@
|
|||
@import '@procyon/styles/global.css';
|
||||
|
||||
@import "./variables.css";
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;700&display=swap');
|
||||
|
||||
body {
|
||||
@apply bg-white text-black text-sm;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
const postcss = require('@procyon/styles/postcss.config');
|
||||
const configPath = require.resolve('./tailwind.config.js');
|
||||
|
||||
module.exports = postcss({ tailwindConfigFile: configPath });
|
|
@ -1,23 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
const plugin = require('tailwindcss/plugin');
|
||||
|
||||
module.exports = {
|
||||
presets: [require('@procyon/styles/tailwind.config')],
|
||||
content: [
|
||||
path.resolve(__dirname + '../../**/*.{js,ts,tsx}'),
|
||||
path.resolve(__dirname + '../../../node_modules/@procyon/**/*.{js,ts,tsx}'),
|
||||
],
|
||||
safelist: require('@procyon/styles/tailwind.config').safelist,
|
||||
theme: {
|
||||
extend: require('./theme'),
|
||||
},
|
||||
variants: {
|
||||
extend: {
|
||||
borderWidth: ['last'],
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
plugin(require('./components/component')),
|
||||
],
|
||||
};
|
18
source/ui/src/styles/tailwind.config.ts
Normal file
18
source/ui/src/styles/tailwind.config.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import type { Config } from 'tailwindcss';
|
||||
import plugin from 'tailwindcss/plugin';
|
||||
import path from 'path';
|
||||
|
||||
export default {
|
||||
presets: [require('@procyon/styles/tailwind.config')],
|
||||
content: [
|
||||
path.resolve(__dirname + '../../app/*.{js,ts,tsx}'),
|
||||
path.resolve(__dirname + '../../pages/*.{js,ts,tsx}'),
|
||||
path.resolve(__dirname + '../../components/*.{js,ts,tsx}'),
|
||||
path.resolve(__dirname + '../../../node_modules/@procyon/**/*.{js,ts,tsx}'),
|
||||
],
|
||||
safelist: require('@procyon/styles/tailwind.config').safelist,
|
||||
theme: {
|
||||
extend: require('./theme'),
|
||||
},
|
||||
plugins: [plugin(require('./components/component'))],
|
||||
} satisfies Config;
|
|
@ -1,10 +0,0 @@
|
|||
const { pallete } = require('@procyon/styles/utils/color');
|
||||
|
||||
module.exports = {
|
||||
colors: {
|
||||
disabled: pallete('disabled'),
|
||||
},
|
||||
borderWidth: {
|
||||
1: '1px',
|
||||
},
|
||||
};
|
12
source/ui/src/styles/theme.ts
Normal file
12
source/ui/src/styles/theme.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
// @ts-nocheck
|
||||
|
||||
import palette from '@procyon/styles/palette';
|
||||
|
||||
module.exports = {
|
||||
colors: {
|
||||
...palette,
|
||||
},
|
||||
borderWidth: {
|
||||
1: '1px',
|
||||
},
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
:root {
|
||||
--color-h: 0;
|
||||
--color-s: 0%;
|
||||
--color-l: 0%;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
declare global {
|
||||
interface Window {
|
||||
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any;
|
||||
}
|
||||
|
||||
namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
ENDPOINT_BASE_URL: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default global;
|
5
source/ui/src/types/next-env.d.ts
vendored
Normal file
5
source/ui/src/types/next-env.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
8
source/ui/src/types/yup.d.ts
vendored
8
source/ui/src/types/yup.d.ts
vendored
|
@ -1,8 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import { StringSchema } from 'yup';
|
||||
|
||||
declare module 'yup' {
|
||||
interface StringSchema {
|
||||
// place custom Yup definition of validation
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// @ts-nocheck
|
||||
// place import for custom Yup validations
|
||||
|
||||
import * as Yup from 'yup';
|
||||
import * as Yup from 'src/utils/yup';
|
||||
|
||||
Yup.setLocale({
|
||||
mixed: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue