WIP: feat: Create new db app #32
1
db
1
db
@ -1 +0,0 @@
|
||||
Subproject commit 9e1c6c96da221f7c5434816aaa3c933d1622cb16
|
11
db/.editorconfig
Normal file
11
db/.editorconfig
Normal file
@ -0,0 +1,11 @@
|
||||
# https://EditorConfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
3
db/.eslintrc.js
Normal file
3
db/.eslintrc.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
extends: ["blitz"],
|
||||
}
|
53
db/.gitignore
vendored
Normal file
53
db/.gitignore
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
# dependencies
|
||||
node_modules
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.pnp.*
|
||||
.npm
|
||||
web_modules/
|
||||
|
||||
# blitz
|
||||
/.blitz/
|
||||
/.next/
|
||||
*.sqlite
|
||||
*.sqlite-journal
|
||||
.now
|
||||
.blitz**
|
||||
blitz-log.log
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
.envrc
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Testing
|
||||
.coverage
|
||||
*.lcov
|
||||
.nyc_output
|
||||
lib-cov
|
||||
|
||||
# Caches
|
||||
*.tsbuildinfo
|
||||
.eslintcache
|
||||
.node_repl_history
|
||||
.yarn-integrity
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
7
db/.npmrc
Normal file
7
db/.npmrc
Normal file
@ -0,0 +1,7 @@
|
||||
save-exact=true
|
||||
legacy-peer-deps=true
|
||||
|
||||
public-hoist-pattern[]=next
|
||||
public-hoist-pattern[]=secure-password
|
||||
public-hoist-pattern[]=*jest*
|
||||
public-hoist-pattern[]=@testing-library/*
|
10
db/.prettierignore
Normal file
10
db/.prettierignore
Normal file
@ -0,0 +1,10 @@
|
||||
.gitkeep
|
||||
.env*
|
||||
*.ico
|
||||
*.lock
|
||||
.next
|
||||
.blitz
|
||||
.yarn
|
||||
.pnp.*
|
||||
node_modules
|
||||
.blitz.config.compiled.js
|
116
db/README.md
Normal file
116
db/README.md
Normal file
@ -0,0 +1,116 @@
|
||||
[![Blitz.js](https://raw.githubusercontent.com/blitz-js/art/master/github-cover-photo.png)](https://blitzjs.com)
|
||||
|
||||
This is a minimal [Blitz.js](https://github.com/blitz-js/blitz) app.
|
||||
|
||||
# **db**
|
||||
|
||||
## Getting Started
|
||||
|
||||
Run your app in the development mode.
|
||||
|
||||
```
|
||||
blitz dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
## Tests
|
||||
|
||||
Runs your tests using Jest.
|
||||
|
||||
```
|
||||
yarn test
|
||||
```
|
||||
|
||||
Blitz comes with a test setup using [Jest](https://jestjs.io/) and [react-testing-library](https://testing-library.com/).
|
||||
|
||||
## Commands
|
||||
|
||||
Blitz comes with a powerful CLI that is designed to make development easy and fast. You can install it with `npm i -g blitz`
|
||||
|
||||
```
|
||||
blitz [COMMAND]
|
||||
|
||||
dev Start a development server
|
||||
build Create a production build
|
||||
start Start a production server
|
||||
export Export your Blitz app as a static application
|
||||
prisma Run prisma commands
|
||||
generate Generate new files for your Blitz project
|
||||
console Run the Blitz console REPL
|
||||
install Install a recipe
|
||||
help Display help for blitz
|
||||
test Run project tests
|
||||
```
|
||||
|
||||
You can read more about it on the [CLI Overview](https://blitzjs.com/docs/cli-overview) documentation.
|
||||
|
||||
## What's included?
|
||||
|
||||
Here is the starting structure of your app.
|
||||
|
||||
```
|
||||
db
|
||||
├── app/
|
||||
│ ├── pages/
|
||||
│ │ ├── _app.tsx
|
||||
│ │ ├── _document.tsx
|
||||
│ │ ├── 404.tsx
|
||||
│ │ ├── index.test.tsx
|
||||
│ │ └── index.tsx
|
||||
├── public/
|
||||
│ ├── favicon.ico
|
||||
│ └── logo.png
|
||||
├── test/
|
||||
│ ├── setup.ts
|
||||
│ └── utils.tsx
|
||||
├── .eslintrc.js
|
||||
├── babel.config.js
|
||||
├── blitz.config.ts
|
||||
├── jest.config.ts
|
||||
├── package.json
|
||||
├── README.md
|
||||
├── tsconfig.json
|
||||
└── types.ts
|
||||
```
|
||||
|
||||
These files are:
|
||||
|
||||
- The `app/` folder is a container for most of your project. This is where you’ll put any pages or API routes.
|
||||
|
||||
- `public/` is a folder where you will put any static assets. If you have images, files, or videos which you want to use in your app, this is where to put them.
|
||||
|
||||
- `test/` is a folder where you can put test utilities and integration tests.
|
||||
|
||||
- `package.json` contains information about your dependencies and devDependencies. If you’re using a tool like `npm` or `yarn`, you won’t have to worry about this much.
|
||||
|
||||
- `tsconfig.json` is our recommended setup for TypeScript.
|
||||
|
||||
- `.babel.config.js`, `.eslintrc.js`, `.env`, etc. ("dotfiles") are configuration files for various bits of JavaScript tooling.
|
||||
|
||||
- `blitz.config.ts` is for advanced custom configuration of Blitz. [Here you can learn how to use it](https://blitzjs.com/docs/blitz-config).
|
||||
|
||||
- `jest.config.js` contains config for Jest tests. You can [customize it if needed](https://jestjs.io/docs/en/configuration).
|
||||
|
||||
You can read more about it in the [File Structure](https://blitzjs.com/docs/file-structure) section of the documentation.
|
||||
|
||||
### Tools included
|
||||
|
||||
Blitz comes with a set of tools that corrects and formats your code, facilitating its future maintenance. You can modify their options and even uninstall them.
|
||||
|
||||
- **ESLint**: It lints your code: searches for bad practices and tell you about it. You can customize it via the `.eslintrc.js`, and you can install (or even write) plugins to have it the way you like it. It already comes with the [`blitz`](https://github.com/blitz-js/blitz/tree/canary/packages/eslint-config) config, but you can remove it safely. [Learn More](https://blitzjs.com/docs/eslint-config).
|
||||
- **Husky**: It adds [githooks](https://git-scm.com/docs/githooks), little pieces of code that get executed when certain Git events are triggerd. For example, `pre-commit` is triggered just before a commit is created. You can see the current hooks inside `.husky/`. If are having problems commiting and pushing, check out ther [troubleshooting](https://typicode.github.io/husky/#/?id=troubleshoot) guide. [Learn More](https://blitzjs.com/docs/husky-config).
|
||||
- **Prettier**: It formats your code to look the same everywhere. You can configure it via the `.prettierrc` file. The `.prettierignore` contains the files that should be ignored by Prettier; useful when you have large files or when you want to keep a custom formatting. [Learn More](https://blitzjs.com/docs/prettier-config).
|
||||
|
||||
## Learn more
|
||||
|
||||
Read the [Blitz.js Documentation](https://blitzjs.com/docs/getting-started) to learn more.
|
||||
|
||||
The Blitz community is warm, safe, diverse, inclusive, and fun! Feel free to reach out to us in any of our communication channels.
|
||||
|
||||
- [Website](https://blitzjs.com)
|
||||
- [Discord](https://blitzjs.com/discord)
|
||||
- [Report an issue](https://github.com/blitz-js/blitz/issues/new/choose)
|
||||
- [Forum discussions](https://github.com/blitz-js/blitz/discussions)
|
||||
- [How to Contribute](https://blitzjs.com/docs/contributing)
|
||||
- [Sponsor or donate](https://github.com/blitz-js/blitz#sponsors-and-donations)
|
59
db/app/core/components/DarkModeToggle.tsx
Normal file
59
db/app/core/components/DarkModeToggle.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import { Box, IconButton, Theme } from '@mui/material'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
import Brightness4Icon from '@mui/icons-material/Brightness4'
|
||||
import Brightness7Icon from '@mui/icons-material/Brightness7'
|
||||
import { ThemeMode } from '../state/ThemeMode'
|
||||
import { useGlobalState } from '../state/GlobalState'
|
||||
import { useCallback } from 'react'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
modeToggleButtonHolder: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: 'primary',
|
||||
flexGrow: 1,
|
||||
},
|
||||
iconButton: {
|
||||
ml: 1,
|
||||
},
|
||||
}))
|
||||
|
||||
export const DarkModeToggle = () => {
|
||||
const theme = useTheme()
|
||||
const classes = useStyles()
|
||||
const [preferedColorScheme, setPreferedColorScheme] = useGlobalState(
|
||||
useCallback(
|
||||
(state) => [state.preferedColorScheme, state.setPreferedColorScheme],
|
||||
[],
|
||||
),
|
||||
)
|
||||
|
||||
const toggleColor = () => {
|
||||
const newTheme =
|
||||
preferedColorScheme === ThemeMode.LIGHT_MODE
|
||||
? ThemeMode.DARK_MODE
|
||||
: ThemeMode.LIGHT_MODE
|
||||
setPreferedColorScheme(newTheme)
|
||||
}
|
||||
|
||||
return (
|
||||
<Box className={classes.modeToggleButtonHolder} id="modeToggleButtonHolder">
|
||||
{theme.palette.mode} mode
|
||||
<IconButton
|
||||
className={classes.iconButton}
|
||||
sx={{ ml: 1 }}
|
||||
onClick={toggleColor}
|
||||
color="inherit"
|
||||
id="modeToggleButton"
|
||||
>
|
||||
{theme.palette.mode === 'dark' ? (
|
||||
<Brightness7Icon />
|
||||
) : (
|
||||
<Brightness4Icon />
|
||||
)}
|
||||
</IconButton>
|
||||
</Box>
|
||||
)
|
||||
}
|
23
db/app/core/components/Footer.tsx
Normal file
23
db/app/core/components/Footer.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import {Box, Typography} from '@mui/material'
|
||||
import {makeStyles} from '@mui/styles'
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
footerHolder: {
|
||||
display: 'flex',
|
||||
flex: '0 1 3vh',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: '0 10vw 0 10vw'
|
||||
}
|
||||
}))
|
||||
|
||||
export const Footer = () => {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<Box className={classes.footerHolder}>
|
||||
<Typography id={"footer"}>SPT-Aki ©2021 Created by Rev and Shirito</Typography>
|
||||
</Box>
|
||||
)
|
||||
}
|
86
db/app/core/components/Header.tsx
Normal file
86
db/app/core/components/Header.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
import { Box, Link, Theme } from '@mui/material'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import { useCallback } from 'react';
|
||||
import { useGlobalState } from '../state/GlobalState';
|
||||
import { HeaderForm } from './HeaderForm';
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
headerContainer: {
|
||||
display: 'flex',
|
||||
flex: '0 1 3vh',
|
||||
flexDirection: 'row',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
alignItems: 'center',
|
||||
padding: '0 10vw 0 10vw',
|
||||
},
|
||||
linksContainer: {
|
||||
display: 'flex',
|
||||
flexGrow: 2,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
},
|
||||
formContainer: {
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
},
|
||||
link: {
|
||||
display: 'flex',
|
||||
padding: '0 1vw 0 1vw',
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
borderBottom: `1px solid transparent`,
|
||||
'&:hover': {
|
||||
borderBottom: `1px solid ${theme.palette.action.hover}`,
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
export const Header = () => {
|
||||
const classes = useStyles()
|
||||
const websiteLink = useGlobalState(useCallback((state) => state.sptarkovWebsiteUrl,[]))
|
||||
const workshopLink = useGlobalState(useCallback((state) => state.sptarkovWorkshopUrl,[]))
|
||||
const documentationLink = useGlobalState(useCallback((state) => state.sptarkovDocumentationUrl,[]))
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box className={classes.headerContainer}>
|
||||
<Box className={classes.linksContainer}>
|
||||
<Link
|
||||
underline="hover"
|
||||
color="inherit"
|
||||
id="website-link"
|
||||
href={websiteLink}
|
||||
className={classes.link}
|
||||
>
|
||||
Website
|
||||
</Link>
|
||||
<Link
|
||||
underline="hover"
|
||||
color="inherit"
|
||||
id="workshop-link"
|
||||
href={workshopLink}
|
||||
className={classes.link}
|
||||
>
|
||||
Workshop
|
||||
</Link>
|
||||
<Link
|
||||
underline="hover"
|
||||
color="inherit"
|
||||
id="documentation-link"
|
||||
href={documentationLink}
|
||||
className={classes.link}
|
||||
>
|
||||
Documentation
|
||||
</Link>
|
||||
</Box>
|
||||
<Box className={classes.formContainer}>
|
||||
<HeaderForm/>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
29
db/app/core/components/HeaderForm.tsx
Normal file
29
db/app/core/components/HeaderForm.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import { DarkModeToggle } from './DarkModeToggle'
|
||||
import { LocaleSelect } from './LocaleSelect'
|
||||
import { JsonTheme } from './JsonTheme'
|
||||
import { Theme } from '@mui/material'
|
||||
import { makeStyles } from '@mui/styles';
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
form: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'flex-end',
|
||||
height: '100%'
|
||||
},
|
||||
}));
|
||||
|
||||
export const HeaderForm = () => {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<>
|
||||
<form className={classes.form}>
|
||||
<DarkModeToggle />
|
||||
<LocaleSelect />
|
||||
<JsonTheme />
|
||||
</form>
|
||||
</>
|
||||
)
|
||||
}
|
69
db/app/core/components/JsonTheme.tsx
Normal file
69
db/app/core/components/JsonTheme.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import {
|
||||
Box,
|
||||
FormControl,
|
||||
MenuItem,
|
||||
Select,
|
||||
Theme,
|
||||
} from '@mui/material'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import { ReactJsonViewThemes } from '../state/ReactJsonViewThemes'
|
||||
import { LocalStorageKeys } from '../dto/SaveKeys'
|
||||
import { useGlobalState } from '../state/GlobalState'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
jsonHolder: {
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
padding: '0 0.5vw 0 0.5vw'
|
||||
},
|
||||
select: {
|
||||
display: 'flex',
|
||||
flexGrow: 1
|
||||
}
|
||||
}))
|
||||
|
||||
export const JsonTheme = () => {
|
||||
const classes = useStyles()
|
||||
const [preferedJsonViewerTheme, setPreferedJsonViewerTheme] = useGlobalState(
|
||||
useCallback(
|
||||
(state) => [
|
||||
state.preferedJsonViewerTheme,
|
||||
state.setPreferedJsonViewerTheme,
|
||||
],
|
||||
[],
|
||||
),
|
||||
)
|
||||
return (
|
||||
<>
|
||||
<Box className={classes.jsonHolder}>
|
||||
<FormControl fullWidth variant="standard">
|
||||
<Select
|
||||
displayEmpty
|
||||
className={classes.select}
|
||||
labelId="react-json-view-theme"
|
||||
value={preferedJsonViewerTheme}
|
||||
label="JSON theme"
|
||||
onChange={(evt) => {
|
||||
setPreferedJsonViewerTheme(evt.target.value)
|
||||
localStorage.setItem(
|
||||
LocalStorageKeys.PREFERED_JSON_THEME,
|
||||
evt.target.value,
|
||||
)
|
||||
}}
|
||||
id="json-selector"
|
||||
>
|
||||
<MenuItem disabled value="">
|
||||
<em>JSON theme</em>
|
||||
</MenuItem>
|
||||
{ReactJsonViewThemes.map((theme, idx) => (
|
||||
<MenuItem key={idx} value={theme}>
|
||||
{theme}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
54
db/app/core/components/LocaleSelect.tsx
Normal file
54
db/app/core/components/LocaleSelect.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import { Select, MenuItem, Theme, Box, FormControl } from '@mui/material'
|
||||
import {makeStyles} from '@mui/styles'
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useGlobalState } from '../state/GlobalState'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
localeHolder: {
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
padding: '0 0.5vw 0 0.5vw'
|
||||
},
|
||||
select: {
|
||||
display: 'flex',
|
||||
flexGrow: 1
|
||||
}
|
||||
}))
|
||||
|
||||
|
||||
|
||||
export const LocaleSelect = () => {
|
||||
const classes = useStyles()
|
||||
const [preferedLocale, setPreferedLocale] = useGlobalState(useCallback(state => [state.preferedLocale, state.setPreferedLocale],[]))
|
||||
const [localesList, refreshLocalesList] = useGlobalState(useCallback(state => [state.localesList, state.refreshLocalesList],[]))
|
||||
|
||||
useEffect(()=> {refreshLocalesList();}, [refreshLocalesList])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box className={classes.localeHolder}>
|
||||
<FormControl fullWidth variant="standard">
|
||||
<Select
|
||||
displayEmpty
|
||||
className={classes.select}
|
||||
labelId="prefered-locale"
|
||||
value={localesList.length > 0 ? preferedLocale : ''}
|
||||
onChange={(evt) => {
|
||||
setPreferedLocale(evt.target.value)
|
||||
}}
|
||||
id="locale-selector"
|
||||
>
|
||||
<MenuItem disabled value="">
|
||||
<em>Language</em>
|
||||
</MenuItem>
|
||||
{localesList.map((locale, idx) => (
|
||||
<MenuItem key={idx} value={locale}>
|
||||
{locale}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
6
db/app/core/dto/ItemData.ts
Normal file
6
db/app/core/dto/ItemData.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface ItemData {
|
||||
_id: string
|
||||
_name: string
|
||||
_parent?: string
|
||||
_type?: string
|
||||
}
|
5
db/app/core/dto/ItemHierarchy.ts
Normal file
5
db/app/core/dto/ItemHierarchy.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { ItemWithLocale } from './ItemWithLocale';
|
||||
|
||||
export interface ItemHierarchy {
|
||||
[id: string]: ItemWithLocale
|
||||
}
|
5
db/app/core/dto/ItemLocale.ts
Normal file
5
db/app/core/dto/ItemLocale.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface ItemLocale {
|
||||
Description: string
|
||||
Name: string
|
||||
ShortName: string
|
||||
}
|
5
db/app/core/dto/ItemOption.ts
Normal file
5
db/app/core/dto/ItemOption.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface ItemOption {
|
||||
id: string
|
||||
name: string
|
||||
shortName?: string
|
||||
}
|
7
db/app/core/dto/ItemWithLocale.ts
Normal file
7
db/app/core/dto/ItemWithLocale.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { ItemData } from './ItemData';
|
||||
import { ItemLocale } from './ItemLocale';
|
||||
|
||||
export interface ItemWithLocale {
|
||||
item: ItemData
|
||||
locale: ItemLocale
|
||||
}
|
10
db/app/core/dto/SaveKeys.ts
Normal file
10
db/app/core/dto/SaveKeys.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export enum LocalStorageKeys {
|
||||
PREFERED_COLOR_SCHEME = 'db.sp-tarkov.com-prefered-color-scheme',
|
||||
PREFERED_JSON_THEME = 'db.sp-tarkov.com-prefered-json-theme',
|
||||
PREFERED_LOCALE = 'db.sp-tarkov.com-prefered-locale'
|
||||
}
|
||||
|
||||
export enum SessionStorageKeys {
|
||||
LOCALES = 'db.sp-tarkov.com-locales',
|
||||
ITEMS_HIERARCHY = 'db.sp-tarkov.com-items-hierarchy',
|
||||
}
|
33
db/app/core/layouts/Layout.tsx
Normal file
33
db/app/core/layouts/Layout.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import {Box} from '@mui/material'
|
||||
import {Footer} from '../components/Footer'
|
||||
import {Header} from '../components/Header'
|
||||
import {makeStyles} from "@mui/styles";
|
||||
import React, { PropsWithChildren } from "react";
|
||||
// import {InteractiveArea} from "./InteractiveArea";
|
||||
// import {PageNotFound} from "./PageNotFound";
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
container: {
|
||||
background: 'background.default',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flexGrow: 1,
|
||||
height: '100vh',
|
||||
maxheight: '100vh',
|
||||
}
|
||||
}))
|
||||
|
||||
interface Props {}
|
||||
|
||||
export const Layout = (props: PropsWithChildren<Props>) => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
<Box className={classes.container}>
|
||||
<Header/>
|
||||
{props.children}
|
||||
<Footer/>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
122
db/app/core/state/GlobalState.ts
Normal file
122
db/app/core/state/GlobalState.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import { ThemeKeys } from 'react-json-view'
|
||||
import create from 'zustand'
|
||||
// import { getLocaleList } from '../dataaccess/ItemBackend'
|
||||
import { LocalStorageKeys, SessionStorageKeys } from '../dto/SaveKeys'
|
||||
import { ItemHierarchy } from '../dto/ItemHierarchy'
|
||||
import { ReactJsonViewThemes } from './ReactJsonViewThemes'
|
||||
import { ThemeMode } from './ThemeMode'
|
||||
import { ItemWithLocale } from '../dto/ItemWithLocale';
|
||||
|
||||
const getLocaleList = async () => {
|
||||
return null;
|
||||
}
|
||||
|
||||
export interface GlobalState {
|
||||
sptarkovWebsiteUrl: string
|
||||
sptarkovWorkshopUrl: string
|
||||
sptarkovDocumentationUrl: string
|
||||
|
||||
preferedLocale: string
|
||||
setPreferedLocale: (newLocale: string) => void
|
||||
localesList: string[]
|
||||
refreshLocalesList: () => void
|
||||
|
||||
preferedJsonViewerTheme: ThemeKeys
|
||||
setPreferedJsonViewerTheme: (newJsonTheme: string) => void
|
||||
|
||||
preferedColorScheme: string
|
||||
setPreferedColorScheme: (newColorScheme: ThemeMode) => void
|
||||
|
||||
searchInput: string
|
||||
setSearchInput: (newInput: string) => void
|
||||
|
||||
desiredSearchInput: string
|
||||
setDesiredSearchInput: (newInput: string) => void
|
||||
|
||||
itemsHierarchy: ItemHierarchy
|
||||
initHierarchy: () => void
|
||||
setHierarchy: (newHierarchy: ItemHierarchy) => void
|
||||
|
||||
selectedItem: ItemWithLocale | undefined
|
||||
setSelectedItem: (newSelectedItem: ItemWithLocale | undefined) => void
|
||||
}
|
||||
|
||||
const isClientSide = () => typeof window == 'object' || typeof window !== 'undefined';
|
||||
|
||||
const preferedLocale = isClientSide() ? localStorage?.getItem(LocalStorageKeys.PREFERED_LOCALE) : null
|
||||
const storedPreferedJsonTheme = isClientSide() ? localStorage?.getItem(
|
||||
LocalStorageKeys.PREFERED_JSON_THEME,
|
||||
) : ThemeMode.DARK_MODE;
|
||||
const preferedColorScheme = isClientSide() ? localStorage?.getItem(LocalStorageKeys.PREFERED_COLOR_SCHEME) : ReactJsonViewThemes[0];
|
||||
|
||||
export const useGlobalState = create<GlobalState>((set) => ({
|
||||
sptarkovWebsiteUrl: process.env.REACT_APP_SPTARKOV_HOME ? process.env.REACT_APP_SPTARKOV_HOME : '',
|
||||
sptarkovWorkshopUrl: process.env.REACT_APP_SPTARKOV_WORKSHOP ? process.env.REACT_APP_SPTARKOV_WORKSHOP : '',
|
||||
sptarkovDocumentationUrl: process.env.REACT_APP_SPTARKOV_DOCUMENTATION ? process.env.REACT_APP_SPTARKOV_DOCUMENTATION : '',
|
||||
|
||||
// Locale
|
||||
preferedLocale: preferedLocale ? preferedLocale : 'en',
|
||||
setPreferedLocale: (newLocale: string) => {
|
||||
if (isClientSide())
|
||||
localStorage?.setItem(LocalStorageKeys.PREFERED_LOCALE, newLocale)
|
||||
set((_state) => ({ preferedLocale: newLocale }))
|
||||
},
|
||||
localesList: [],
|
||||
refreshLocalesList: async () => {
|
||||
const locales = isClientSide() ? sessionStorage?.getItem(SessionStorageKeys.LOCALES) : "[en]";
|
||||
const localesList = locales !== null && locales !== undefined && locales !== 'undefined' && locales !== 'null' ? JSON.parse(locales) : await getLocaleList()
|
||||
if (!locales && isClientSide()) sessionStorage?.setItem(SessionStorageKeys.LOCALES, JSON.stringify(localesList ? localesList : null))
|
||||
set((_state) => ({ localesList: localesList ? localesList : [] }))
|
||||
},
|
||||
|
||||
// Json viewer theme
|
||||
preferedJsonViewerTheme:
|
||||
storedPreferedJsonTheme &&
|
||||
ReactJsonViewThemes.includes(storedPreferedJsonTheme)
|
||||
? (storedPreferedJsonTheme as ThemeKeys)
|
||||
: (ReactJsonViewThemes[0] as ThemeKeys),
|
||||
setPreferedJsonViewerTheme: (newJsonTheme: string) => {
|
||||
if (isClientSide()) localStorage?.setItem(LocalStorageKeys.PREFERED_JSON_THEME, newJsonTheme)
|
||||
set((_state) => ({ preferedJsonViewerTheme: newJsonTheme as ThemeKeys }))
|
||||
},
|
||||
|
||||
// Prefered theme
|
||||
preferedColorScheme: preferedColorScheme
|
||||
? preferedColorScheme
|
||||
: ThemeMode.DARK_MODE,
|
||||
setPreferedColorScheme: (newColorScheme: ThemeMode) => {
|
||||
if (isClientSide()) localStorage?.setItem(LocalStorageKeys.PREFERED_COLOR_SCHEME, newColorScheme)
|
||||
set((_state) => ({ preferedColorScheme: newColorScheme }))
|
||||
},
|
||||
|
||||
// SearchInput
|
||||
searchInput: '',
|
||||
setSearchInput: (newInput: string) =>
|
||||
set((_state) => ({ searchInput: newInput })),
|
||||
desiredSearchInput: '',
|
||||
setDesiredSearchInput: (newInput: string) =>
|
||||
set((_state) => ({ desiredSearchInput: newInput })),
|
||||
|
||||
// Hierarchy
|
||||
itemsHierarchy: {},
|
||||
initHierarchy: () => {
|
||||
const itemsHierarchy = isClientSide() ? sessionStorage?.getItem(SessionStorageKeys.ITEMS_HIERARCHY) : "{}";
|
||||
if (itemsHierarchy !== null && itemsHierarchy !== undefined && itemsHierarchy !== 'undefined') {
|
||||
set((_state) => ({ itemsHierarchy: JSON.parse(itemsHierarchy) }))
|
||||
}
|
||||
},
|
||||
setHierarchy: (newHierarchy: ItemHierarchy) => {
|
||||
set((state) => {
|
||||
const newStateHierarchy = Object.assign({}, state.itemsHierarchy, newHierarchy);
|
||||
if (isClientSide()) sessionStorage?.setItem(SessionStorageKeys.ITEMS_HIERARCHY, JSON.stringify(newStateHierarchy ? newStateHierarchy : null))
|
||||
return ({
|
||||
itemsHierarchy: newStateHierarchy,
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
// Selected item
|
||||
selectedItem: undefined,
|
||||
setSelectedItem: (newSelectedItem: ItemWithLocale | undefined) =>
|
||||
set((_state) => ({ selectedItem: newSelectedItem })),
|
||||
}))
|
40
db/app/core/state/ReactJsonViewThemes.ts
Normal file
40
db/app/core/state/ReactJsonViewThemes.ts
Normal file
@ -0,0 +1,40 @@
|
||||
// No choice but to hard code since it is only a type in the library
|
||||
export const ReactJsonViewThemes = [
|
||||
'apathy',
|
||||
'apathy:inverted',
|
||||
'ashes',
|
||||
'bespin',
|
||||
'brewer',
|
||||
'bright:inverted',
|
||||
'bright',
|
||||
'chalk',
|
||||
'codeschool',
|
||||
'colors',
|
||||
'eighties',
|
||||
'embers',
|
||||
'flat',
|
||||
'google',
|
||||
'grayscale',
|
||||
'grayscale:inverted',
|
||||
'greenscreen',
|
||||
'harmonic',
|
||||
'hopscotch',
|
||||
'isotope',
|
||||
'marrakesh',
|
||||
'mocha',
|
||||
'monokai',
|
||||
'ocean',
|
||||
'paraiso',
|
||||
'pop',
|
||||
'railscasts',
|
||||
'rjv-default',
|
||||
'shapeshifter',
|
||||
'shapeshifter:inverted',
|
||||
'solarized',
|
||||
'summerfruit',
|
||||
'summerfruit:inverted',
|
||||
'threezerotwofour',
|
||||
'tomorrow',
|
||||
'tube',
|
||||
'twilight'
|
||||
]
|
4
db/app/core/state/ThemeMode.ts
Normal file
4
db/app/core/state/ThemeMode.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export enum ThemeMode {
|
||||
LIGHT_MODE = 'light',
|
||||
DARK_MODE = 'dark'
|
||||
}
|
66
db/app/core/theme/Theme.ts
Normal file
66
db/app/core/theme/Theme.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import {createTheme, Palette} from '@mui/material/styles';
|
||||
|
||||
export const getTheme = (palette: Palette) => createTheme({
|
||||
palette: palette,
|
||||
components: {
|
||||
MuiLink: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'&:hover': {
|
||||
textDecoration: 'none'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
MuiInput:{
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'&:before': {
|
||||
borderColor: 'transparent',
|
||||
},
|
||||
'&:after': {
|
||||
borderColor: 'transparent',
|
||||
},
|
||||
'&:hover:not(.Mui-disabled):before': {
|
||||
borderColor: palette.action.hover,
|
||||
}
|
||||
},
|
||||
input:{
|
||||
'&:focus': {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
MuiTextField: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
'& label.Mui-focused': {
|
||||
color: palette.action.hover,
|
||||
},
|
||||
'& .MuiFilledInput-underline:after': {
|
||||
borderBottomColor: palette.action.hover,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
MuiInputBase:{
|
||||
styleOverrides:{
|
||||
root:{
|
||||
'&.Mui-focused .MuiOutlinedInput-notchedOutline':{
|
||||
borderColor: `${palette.action.hover} !important`,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
MuiFormLabel: {
|
||||
styleOverrides: {
|
||||
root:{
|
||||
'&.Mui-focused .MuiInputLabel': {
|
||||
color: palette.action.hover
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
19
db/app/core/theme/darkTheme.ts
Normal file
19
db/app/core/theme/darkTheme.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {ThemeMode} from '../state/ThemeMode';
|
||||
import {common, grey, lightBlue, yellow} from '@mui/material/colors';
|
||||
import createPalette from "@mui/material/styles/createPalette";
|
||||
|
||||
export const darkPalette = createPalette({
|
||||
mode: ThemeMode.DARK_MODE,
|
||||
background: {
|
||||
default: grey[900],
|
||||
paper: '#121212'
|
||||
},
|
||||
text: {
|
||||
primary: common.white,
|
||||
secondary: '#8894a2',
|
||||
disabled: lightBlue[100]
|
||||
},
|
||||
action: {
|
||||
hover: yellow[700]
|
||||
},
|
||||
});
|
19
db/app/core/theme/lightTheme.ts
Normal file
19
db/app/core/theme/lightTheme.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {ThemeMode} from '../state/ThemeMode';
|
||||
import {blue, common, grey} from "@mui/material/colors";
|
||||
import createPalette from "@mui/material/styles/createPalette";
|
||||
|
||||
export const lightPalette = createPalette({
|
||||
mode: ThemeMode.LIGHT_MODE,
|
||||
background: {
|
||||
default: grey[100],
|
||||
paper: grey[300]
|
||||
},
|
||||
text: {
|
||||
primary: common.black,
|
||||
secondary: blue[500],
|
||||
disabled: grey[600]
|
||||
},
|
||||
action: {
|
||||
hover: blue[500],
|
||||
}
|
||||
});
|
48
db/app/pages/404.tsx
Normal file
48
db/app/pages/404.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import {Box, Theme, Typography} from '@mui/material'
|
||||
import {makeStyles} from "@mui/styles";
|
||||
import { Layout } from 'app/core/layouts/Layout';
|
||||
import { BlitzPage } from 'blitz';
|
||||
import React from "react";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
searchContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexGrow: 1,
|
||||
padding: '2vh 2vw 1vh 2vw'
|
||||
},
|
||||
notFoundAreaHolder: {
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
flexDirection: 'column',
|
||||
background: theme.palette.background.paper,
|
||||
padding: '2vh 2vw 2vh 2vw',
|
||||
},
|
||||
notFoundContainer: {
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
flexDirection: 'column',
|
||||
width: "100%",
|
||||
alignItems: "center",
|
||||
paddingTop: "10vh"
|
||||
},
|
||||
}))
|
||||
|
||||
const PageNotFound: BlitzPage = () => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
<Box className={classes.searchContainer}>
|
||||
<Box className={classes.notFoundAreaHolder}>
|
||||
<Box className={classes.notFoundContainer}>
|
||||
<Typography id={'not-found-message'} variant={"h3"}>This page does not exist !</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
PageNotFound.getLayout = (page) => <Layout>{page}</Layout>
|
||||
|
||||
export default PageNotFound;
|
78
db/app/pages/_app.tsx
Normal file
78
db/app/pages/_app.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import {
|
||||
AppProps,
|
||||
ErrorBoundary,
|
||||
ErrorComponent,
|
||||
ErrorFallbackProps,
|
||||
useQueryErrorResetBoundary,
|
||||
} from "blitz"
|
||||
|
||||
import CssBaseline from "@mui/material/CssBaseline";
|
||||
import { ThemeProvider, createTheme } from "@mui/material/styles";
|
||||
import React, { useEffect } from "react";
|
||||
import { useMediaQuery } from "@mui/material";
|
||||
import { useGlobalState } from "app/core/state/GlobalState";
|
||||
import { LocalStorageKeys } from "app/core/dto/SaveKeys";
|
||||
import { ThemeMode } from "app/core/state/ThemeMode";
|
||||
import { darkPalette } from "app/core/theme/darkTheme";
|
||||
import { lightPalette } from "app/core/theme/lightTheme";
|
||||
import { getTheme } from "app/core/theme/Theme";
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
||||
const [preferedColorScheme ,setPreferedColorScheme] = useGlobalState(state => [state.preferedColorScheme, state.setPreferedColorScheme])
|
||||
|
||||
useEffect(() => {
|
||||
const localPreferedTheme = localStorage.getItem(LocalStorageKeys.PREFERED_COLOR_SCHEME);
|
||||
if (localPreferedTheme) {
|
||||
setPreferedColorScheme(localPreferedTheme as ThemeMode)
|
||||
return
|
||||
}
|
||||
|
||||
const preferedTheme = prefersDarkMode ? ThemeMode.DARK_MODE : ThemeMode.LIGHT_MODE;
|
||||
setPreferedColorScheme(preferedTheme)
|
||||
// eslint-disable-next-line
|
||||
}, [prefersDarkMode]) // Need to be only used on prefersDarkMode change
|
||||
const getLayout = Component.getLayout || ((page) => page)
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={getTheme(preferedColorScheme === ThemeMode.DARK_MODE ? darkPalette : lightPalette)}>
|
||||
<CssBaseline />
|
||||
<ErrorBoundary
|
||||
FallbackComponent={RootErrorFallback}
|
||||
onReset={useQueryErrorResetBoundary().reset}
|
||||
>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</ErrorBoundary>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
||||
const [preferedColorScheme ,setPreferedColorScheme] = useGlobalState(state => [state.preferedColorScheme, state.setPreferedColorScheme])
|
||||
|
||||
useEffect(() => {
|
||||
const localPreferedTheme = localStorage.getItem(LocalStorageKeys.PREFERED_COLOR_SCHEME);
|
||||
if (localPreferedTheme) {
|
||||
setPreferedColorScheme(localPreferedTheme as ThemeMode)
|
||||
return
|
||||
}
|
||||
|
||||
const preferedTheme = prefersDarkMode ? ThemeMode.DARK_MODE : ThemeMode.LIGHT_MODE;
|
||||
setPreferedColorScheme(preferedTheme)
|
||||
// eslint-disable-next-line
|
||||
}, [prefersDarkMode]) // Need to be only used on prefersDarkMode change
|
||||
|
||||
return (
|
||||
<>
|
||||
<ThemeProvider theme={getTheme(preferedColorScheme === ThemeMode.DARK_MODE ? darkPalette : lightPalette)}>
|
||||
<CssBaseline/>
|
||||
<MainPage/>
|
||||
</ThemeProvider>
|
||||
</>
|
||||
)
|
||||
*/
|
||||
|
||||
function RootErrorFallback({ error }: ErrorFallbackProps) {
|
||||
return <ErrorComponent statusCode={error.statusCode || 400} title={error.message || error.name} />
|
||||
}
|
50
db/app/pages/_document.tsx
Normal file
50
db/app/pages/_document.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import {
|
||||
DocumentContext,
|
||||
Document,
|
||||
Html,
|
||||
DocumentHead,
|
||||
Main,
|
||||
BlitzScript /*DocumentContext*/,
|
||||
} from "blitz";
|
||||
|
||||
import React from "react";
|
||||
import { ServerStyleSheets } from "@mui/styles";
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(ctx: DocumentContext) {
|
||||
const sheets = new ServerStyleSheets();
|
||||
const originalRenderPage = ctx.renderPage;
|
||||
|
||||
ctx.renderPage = () => originalRenderPage({
|
||||
enhanceApp: App => props => sheets.collect(<App {...props} />)
|
||||
});
|
||||
|
||||
const initialProps = await Document.getInitialProps(ctx);
|
||||
|
||||
return {
|
||||
...initialProps,
|
||||
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()]
|
||||
};
|
||||
}
|
||||
|
||||
// Only uncomment if you need to customize this behaviour
|
||||
// static async getInitialProps(ctx: DocumentContext) {
|
||||
// const initialProps = await Document.getInitialProps(ctx)
|
||||
// return {...initialProps}
|
||||
// }
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<DocumentHead />
|
||||
<title>Item Finder</title>
|
||||
<body>
|
||||
<Main />
|
||||
<BlitzScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument
|
13
db/app/pages/index.test.tsx
Normal file
13
db/app/pages/index.test.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import { render } from "test/utils"
|
||||
|
||||
import Home from "./index"
|
||||
|
||||
test.skip("renders blitz documentation link", () => {
|
||||
// This is an example of how to ensure a specific item is in the document
|
||||
// But it's disabled by default (by test.skip) so the test doesn't fail
|
||||
// when you remove the the default content from the page
|
||||
|
||||
const { getByText } = render(<Home />)
|
||||
const linkElement = getByText(/Documentation/i)
|
||||
expect(linkElement).toBeInTheDocument()
|
||||
})
|
228
db/app/pages/index.tsx
Normal file
228
db/app/pages/index.tsx
Normal file
@ -0,0 +1,228 @@
|
||||
// import { Image, BlitzPage } from "blitz"
|
||||
// import logo from "public/logo.png"
|
||||
|
||||
// /*
|
||||
// * This file is just for a pleasant getting started page for your new app.
|
||||
// * You can delete everything in here and start from scratch if you like.
|
||||
// */
|
||||
|
||||
// const Home: BlitzPage = () => {
|
||||
// return (
|
||||
// <div className="container">
|
||||
// <main>
|
||||
// <div className="logo">
|
||||
// <Image src={logo} alt="blitzjs" />
|
||||
// </div>
|
||||
// <p>
|
||||
// <strong>Congrats!</strong> Your app is ready.
|
||||
// </p>
|
||||
// <div className="buttons" style={{ marginTop: "5rem" }}>
|
||||
// <a
|
||||
// className="button"
|
||||
// href="https://blitzjs.com/docs/getting-started?utm_source=blitz-new&utm_medium=app-template&utm_campaign=blitz-new"
|
||||
// target="_blank"
|
||||
// rel="noopener noreferrer"
|
||||
// >
|
||||
// Documentation
|
||||
// </a>
|
||||
// <a
|
||||
// className="button-outline"
|
||||
// href="https://github.com/blitz-js/blitz"
|
||||
// target="_blank"
|
||||
// rel="noopener noreferrer"
|
||||
// >
|
||||
// Github Repo
|
||||
// </a>
|
||||
// <a
|
||||
// className="button-outline"
|
||||
// href="https://discord.blitzjs.com"
|
||||
// target="_blank"
|
||||
// rel="noopener noreferrer"
|
||||
// >
|
||||
// Discord Community
|
||||
// </a>
|
||||
// </div>
|
||||
// </main>
|
||||
|
||||
// <footer>
|
||||
// <a
|
||||
// href="https://blitzjs.com?utm_source=blitz-new&utm_medium=app-template&utm_campaign=blitz-new"
|
||||
// target="_blank"
|
||||
// rel="noopener noreferrer"
|
||||
// >
|
||||
// Powered by Blitz.js
|
||||
// </a>
|
||||
// </footer>
|
||||
|
||||
// <style jsx global>{`
|
||||
// @import url("https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@300;700&display=swap");
|
||||
|
||||
// html,
|
||||
// body {
|
||||
// padding: 0;
|
||||
// margin: 0;
|
||||
// font-family: "Libre Franklin", -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
// Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
// }
|
||||
|
||||
// * {
|
||||
// -webkit-font-smoothing: antialiased;
|
||||
// -moz-osx-font-smoothing: grayscale;
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
// .container {
|
||||
// min-height: 100vh;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// }
|
||||
|
||||
// main {
|
||||
// padding: 5rem 0;
|
||||
// flex: 1;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// }
|
||||
|
||||
// main p {
|
||||
// font-size: 1.2rem;
|
||||
// }
|
||||
|
||||
// p {
|
||||
// text-align: center;
|
||||
// }
|
||||
|
||||
// footer {
|
||||
// width: 100%;
|
||||
// height: 60px;
|
||||
// border-top: 1px solid #eaeaea;
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// background-color: #45009d;
|
||||
// }
|
||||
|
||||
// footer a {
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// }
|
||||
|
||||
// footer a {
|
||||
// color: #f4f4f4;
|
||||
// text-decoration: none;
|
||||
// }
|
||||
|
||||
// .logo {
|
||||
// margin-bottom: 2rem;
|
||||
// }
|
||||
|
||||
// .logo img {
|
||||
// width: 300px;
|
||||
// }
|
||||
|
||||
// .buttons {
|
||||
// display: grid;
|
||||
// grid-auto-flow: column;
|
||||
// grid-gap: 0.5rem;
|
||||
// }
|
||||
// .button {
|
||||
// font-size: 1rem;
|
||||
// background-color: #6700eb;
|
||||
// padding: 1rem 2rem;
|
||||
// color: #f4f4f4;
|
||||
// text-align: center;
|
||||
// }
|
||||
|
||||
// .button.small {
|
||||
// padding: 0.5rem 1rem;
|
||||
// }
|
||||
|
||||
// .button:hover {
|
||||
// background-color: #45009d;
|
||||
// }
|
||||
|
||||
// .button-outline {
|
||||
// border: 2px solid #6700eb;
|
||||
// padding: 1rem 2rem;
|
||||
// color: #6700eb;
|
||||
// text-align: center;
|
||||
// }
|
||||
|
||||
// .button-outline:hover {
|
||||
// border-color: #45009d;
|
||||
// color: #45009d;
|
||||
// }
|
||||
|
||||
// pre {
|
||||
// background: #fafafa;
|
||||
// border-radius: 5px;
|
||||
// padding: 0.75rem;
|
||||
// text-align: center;
|
||||
// }
|
||||
// code {
|
||||
// font-size: 0.9rem;
|
||||
// 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: 800px;
|
||||
// margin-top: 3rem;
|
||||
// }
|
||||
|
||||
// @media (max-width: 600px) {
|
||||
// .grid {
|
||||
// width: 100%;
|
||||
// flex-direction: column;
|
||||
// }
|
||||
// }
|
||||
// `}</style>
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
|
||||
// Home.suppressFirstRenderFlicker = true
|
||||
|
||||
// export default Home
|
||||
|
||||
|
||||
import {Box, Typography} from '@mui/material'
|
||||
import {makeStyles} from "@mui/styles";
|
||||
import React from "react";
|
||||
import { BlitzPage } from 'blitz';
|
||||
import { Layout } from 'app/core/layouts/Layout';
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
container: {
|
||||
background: 'background.default',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flexGrow: 1,
|
||||
height: '100vh',
|
||||
maxheight: '100vh',
|
||||
}
|
||||
}))
|
||||
|
||||
const Search: BlitzPage = () => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
<Box className={classes.container}>
|
||||
<Typography>Searching</Typography>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Search.getLayout = (page) => <Layout>{page}</Layout>
|
||||
|
||||
export default Search;
|
4
db/babel.config.js
Normal file
4
db/babel.config.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
presets: ["blitz/babel"],
|
||||
plugins: [],
|
||||
}
|
6
db/blitz-env.d.ts
vendored
Normal file
6
db/blitz-env.d.ts
vendored
Normal file
@ -0,0 +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.
|
13
db/blitz.config.ts
Normal file
13
db/blitz.config.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { BlitzConfig } from "blitz"
|
||||
|
||||
const config: BlitzConfig = {
|
||||
/* Uncomment this to customize the webpack config
|
||||
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
|
||||
// Note: we provide webpack above so you should not `require` it
|
||||
// Perform customizations to webpack config
|
||||
// Important: return the modified config
|
||||
return config
|
||||
},
|
||||
*/
|
||||
}
|
||||
module.exports = config
|
7
db/jest.config.ts
Normal file
7
db/jest.config.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import type { Config } from "@jest/types"
|
||||
|
||||
const config: Config.InitialOptions = {
|
||||
preset: "blitz",
|
||||
}
|
||||
|
||||
export default config
|
42
db/package.json
Normal file
42
db/package.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "db",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "blitz dev",
|
||||
"build": "blitz build",
|
||||
"start": "blitz start",
|
||||
"lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 100
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,tsx}": [
|
||||
"eslint --fix"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "11.x",
|
||||
"@emotion/styled": "11.x",
|
||||
"@mui/icons-material": "5.2.4",
|
||||
"@mui/material": "5.x",
|
||||
"@mui/styles": "5.x",
|
||||
"blitz": "0.44.4",
|
||||
"react": "18.0.0-beta-149b420f6-20211119",
|
||||
"react-dom": "18.0.0-alpha-5ca4b0433-20211020",
|
||||
"react-json-view": "1.21.3",
|
||||
"zustand": "3.6.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "17.0.37",
|
||||
"eslint": "7.32.0",
|
||||
"lint-staged": "11.3.0-beta.2",
|
||||
"prettier": "2.5.1",
|
||||
"pretty-quick": "3.1.2",
|
||||
"typescript": "~4.5"
|
||||
},
|
||||
"private": true
|
||||
}
|
BIN
db/public/favicon.ico
Normal file
BIN
db/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
db/public/logo.png
Normal file
BIN
db/public/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
4
db/test/setup.ts
Normal file
4
db/test/setup.ts
Normal file
@ -0,0 +1,4 @@
|
||||
// This is the jest 'setupFilesAfterEnv' setup file
|
||||
// It's a good place to set globals, add global before/after hooks, etc
|
||||
|
||||
export {} // so TS doesn't complain
|
105
db/test/utils.tsx
Normal file
105
db/test/utils.tsx
Normal file
@ -0,0 +1,105 @@
|
||||
import { RouterContext, BlitzRouter, BlitzProvider } from "blitz"
|
||||
import { render as defaultRender } from "@testing-library/react"
|
||||
import { renderHook as defaultRenderHook } from "@testing-library/react-hooks"
|
||||
|
||||
export * from "@testing-library/react"
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// This file customizes the render() and renderHook() test functions provided
|
||||
// by React testing library. It adds a router context wrapper with a mocked router.
|
||||
//
|
||||
// You should always import `render` and `renderHook` from this file
|
||||
//
|
||||
// This is the place to add any other context providers you need while testing.
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------
|
||||
// render()
|
||||
// --------------------------------------------------
|
||||
// Override the default test render with our own
|
||||
//
|
||||
// You can override the router mock like this:
|
||||
//
|
||||
// const { baseElement } = render(<MyComponent />, {
|
||||
// router: { pathname: '/my-custom-pathname' },
|
||||
// });
|
||||
// --------------------------------------------------
|
||||
export function render(
|
||||
ui: RenderUI,
|
||||
{ wrapper, router, dehydratedState, ...options }: RenderOptions = {}
|
||||
) {
|
||||
if (!wrapper) {
|
||||
// Add a default context wrapper if one isn't supplied from the test
|
||||
wrapper = ({ children }) => (
|
||||
<BlitzProvider dehydratedState={dehydratedState}>
|
||||
<RouterContext.Provider value={{ ...mockRouter, ...router }}>
|
||||
{children}
|
||||
</RouterContext.Provider>
|
||||
</BlitzProvider>
|
||||
)
|
||||
}
|
||||
return defaultRender(ui, { wrapper, ...options })
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// renderHook()
|
||||
// --------------------------------------------------
|
||||
// Override the default test renderHook with our own
|
||||
//
|
||||
// You can override the router mock like this:
|
||||
//
|
||||
// const result = renderHook(() => myHook(), {
|
||||
// router: { pathname: '/my-custom-pathname' },
|
||||
// });
|
||||
// --------------------------------------------------
|
||||
export function renderHook(
|
||||
hook: RenderHook,
|
||||
{ wrapper, router, dehydratedState, ...options }: RenderHookOptions = {}
|
||||
) {
|
||||
if (!wrapper) {
|
||||
// Add a default context wrapper if one isn't supplied from the test
|
||||
wrapper = ({ children }) => (
|
||||
<BlitzProvider dehydratedState={dehydratedState}>
|
||||
<RouterContext.Provider value={{ ...mockRouter, ...router }}>
|
||||
{children}
|
||||
</RouterContext.Provider>
|
||||
</BlitzProvider>
|
||||
)
|
||||
}
|
||||
return defaultRenderHook(hook, { wrapper, ...options })
|
||||
}
|
||||
|
||||
export const mockRouter: BlitzRouter = {
|
||||
basePath: "",
|
||||
pathname: "/",
|
||||
route: "/",
|
||||
asPath: "/",
|
||||
params: {},
|
||||
query: {},
|
||||
isReady: true,
|
||||
isLocaleDomain: false,
|
||||
isPreview: false,
|
||||
push: jest.fn(),
|
||||
replace: jest.fn(),
|
||||
reload: jest.fn(),
|
||||
back: jest.fn(),
|
||||
prefetch: jest.fn(),
|
||||
beforePopState: jest.fn(),
|
||||
events: {
|
||||
on: jest.fn(),
|
||||
off: jest.fn(),
|
||||
emit: jest.fn(),
|
||||
},
|
||||
isFallback: false,
|
||||
}
|
||||
|
||||
type DefaultParams = Parameters<typeof defaultRender>
|
||||
type RenderUI = DefaultParams[0]
|
||||
type RenderOptions = DefaultParams[1] & { router?: Partial<BlitzRouter>; dehydratedState?: unknown }
|
||||
|
||||
type DefaultHookParams = Parameters<typeof defaultRenderHook>
|
||||
type RenderHook = DefaultHookParams[0]
|
||||
type RenderHookOptions = DefaultHookParams[1] & {
|
||||
router?: Partial<BlitzRouter>
|
||||
dehydratedState?: unknown
|
||||
}
|
24
db/tsconfig.json
Normal file
24
db/tsconfig.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"baseUrl": "./",
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"strictNullChecks": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": ".tsbuildinfo"
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.e2e.ts", "cypress"],
|
||||
"include": ["blitz-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
5
db/types.ts
Normal file
5
db/types.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { DefaultCtx } from "blitz"
|
||||
|
||||
declare module "blitz" {
|
||||
export interface Ctx extends DefaultCtx {}
|
||||
}
|
9739
db/yarn.lock
Normal file
9739
db/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user