WIP: feat: Create new db app #32

Closed
Ghost wants to merge 6 commits from feat/migrate-to-blitzjs into development
43 changed files with 11227 additions and 1 deletions
Showing only changes of commit c57646cf7b - Show all commits

1
db

@ -1 +0,0 @@
Subproject commit 9e1c6c96da221f7c5434816aaa3c933d1622cb16

11
db/.editorconfig Normal file
View 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
View File

@ -0,0 +1,3 @@
module.exports = {
extends: ["blitz"],
}

53
db/.gitignore vendored Normal file
View 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
View 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
View 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
View 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 youll 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 youre using a tool like `npm` or `yarn`, you wont 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)

View 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>
)
}

View 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>
)
}

View 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>
</>
)
}

View 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>
</>
)
}

View 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>
</>
)
}

View 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>
</>
)
}

View File

@ -0,0 +1,6 @@
export interface ItemData {
_id: string
_name: string
_parent?: string
_type?: string
}

View File

@ -0,0 +1,5 @@
import { ItemWithLocale } from './ItemWithLocale';
export interface ItemHierarchy {
[id: string]: ItemWithLocale
}

View File

@ -0,0 +1,5 @@
export interface ItemLocale {
Description: string
Name: string
ShortName: string
}

View File

@ -0,0 +1,5 @@
export interface ItemOption {
id: string
name: string
shortName?: string
}

View File

@ -0,0 +1,7 @@
import { ItemData } from './ItemData';
import { ItemLocale } from './ItemLocale';
export interface ItemWithLocale {
item: ItemData
locale: ItemLocale
}

View 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',
}

View 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>
</>
)
}

View 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 })),
}))

View 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'
]

View File

@ -0,0 +1,4 @@
export enum ThemeMode {
LIGHT_MODE = 'light',
DARK_MODE = 'dark'
}

View 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
}
}
}
}
}
});

View 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]
},
});

View 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
View 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
View 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} />
}

View 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

View 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
View 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
View File

@ -0,0 +1,4 @@
module.exports = {
presets: ["blitz/babel"],
plugins: [],
}

6
db/blitz-env.d.ts vendored Normal file
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
db/public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

4
db/test/setup.ts Normal file
View 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
View 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
View 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
View File

@ -0,0 +1,5 @@
import { DefaultCtx } from "blitz"
declare module "blitz" {
export interface Ctx extends DefaultCtx {}
}

9739
db/yarn.lock Normal file

File diff suppressed because it is too large Load Diff