This commit is contained in:
parent
16b4cce118
commit
c57646cf7b
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