added utils; linters; absolute imports

This commit is contained in:
Myzel394 2022-10-13 21:38:57 +02:00
parent 9c0ee1af2b
commit 550baf1b66
12 changed files with 1480 additions and 9 deletions

24
.eslintrc.json Executable file
View File

@ -0,0 +1,24 @@
{
"extends": [
"plugin:react/recommended",
"plugin:compat/recommended",
"prettier"
],
"env": {
"browser": true,
"es2021": true,
"jest": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 13,
"sourceType": "module"
},
"plugins": ["react", "@typescript-eslint"],
"rules": {
"react/react-in-jsx-scope": "off"
}
}

14
.prettierrc Normal file
View File

@ -0,0 +1,14 @@
{
"endOfLine": "lf",
"printWidth": 80,
"tabWidth": 4,
"trailingComma": "all",
"singleQuote": false,
"useTabs": true,
"semi": false,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"arrowParens": "avoid",
"bracketSpacing": false,
"bracketSameLine": false
}

View File

@ -29,7 +29,14 @@
"@types/react-router-dom": "^5.3.3",
"@types/ua-parser-js": "^0.7.36",
"@types/yup": "^0.32.0",
"@typescript-eslint/eslint-plugin": "^5.40.0",
"@typescript-eslint/parser": "^5.40.0",
"@vitejs/plugin-react": "^2.1.0",
"eslint": "^8.25.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-compat": "^4.0.2",
"eslint-plugin-react": "^7.31.10",
"prettier": "^2.7.1",
"typescript": "^4.6.4",
"vite": "^3.1.0"
}

View File

@ -1,6 +1,6 @@
import {forwardRef, ReactElement, useEffect, useRef, useState} from "react"
import {Paper} from "@mui/material"
import whenElementHasBounds from "utils/when-element-has-bounds"
import whenElementHasBounds from "~/utils/when-element-has-bounds"
export interface MultiStepFormProps {
steps: (() => ReactElement)[]

View File

@ -0,0 +1,39 @@
interface OSUrls {
android: string
// No ios support
}
const createUrl = (url: string, packageName: string): string =>
`intent://${url}#Intent;scheme=https;package=${packageName};end`
const APP_LINK_MAP: Record<string, OSUrls> = {
"googlemail.com": {
android: createUrl("mail.google.com", "com.google.android.gm"),
},
"gmail.com": {
android: createUrl("mail.google.com", "com.google.android.gm"),
},
"gmx.net": {
android: createUrl("gmx.net", "de.gmx.mobile.android.mail"),
},
"web.de": {
android: createUrl("web.de", "de.web.mobile.android.mail"),
},
"t-online.de": {
android: createUrl("t-online.de", "de.telekom.mail"),
},
"magenta.de": {
android: createUrl("t-online.de", "de.telekom.mail"),
},
"outlook.com": {
android: createUrl("outlook.com", "com.microsoft.office.outlook"),
},
"yahoo.com": {
android: createUrl(
"mail.yahoo.com",
"com.yahoo.mobile.client.android.mai",
),
},
}
export default APP_LINK_MAP

View File

@ -0,0 +1,7 @@
import Crypto from "crypto-js"
export default function encryptString(value: string, password: string): string {
const key = `${password}-${process.env.NODE_PUBLIC_NEXT_PUBLIC_PUBLIC_ENCRYPTION_SAL}`
return Crypto.AES.encrypt(value, key).toString()
}

View File

@ -0,0 +1,17 @@
import {FormikHelpers} from "formik"
import parseFastAPIError from "./parse-fastapi-error"
import {AxiosError} from "axios"
export default function handleErrors<T = any, Result = any, Values = any>(
values: T,
setErrors: FormikHelpers<Values>["setErrors"],
) {
return async (callback: (values: T) => Promise<Result>) => {
try {
const result = await callback(values)
return result
} catch (error) {
setErrors(parseFastAPIError(error as AxiosError))
}
}
}

View File

@ -0,0 +1,36 @@
import {AxiosError} from "axios"
import {FormikErrors} from "formik"
export interface FastAPIError {
detail:
| string
| {
loc: ["body" | "path", string]
msg: string
type: string
}[]
}
export default function parseFastAPIError(
rawError: AxiosError,
): FormikErrors<any> {
if (rawError.isAxiosError) {
const fastAPIError = rawError.response?.data as FastAPIError
if (typeof fastAPIError.detail === "string") {
return {detail: fastAPIError.detail}
}
return fastAPIError.detail.reduce((acc, error) => {
const [location, field] = error.loc
if (location === "body") {
acc[field] = error.msg
}
return acc
}, {} as Record<string, string>)
}
return {detail: rawError.message}
}

View File

@ -0,0 +1,14 @@
export default function whenElementHasBounds(
callback: (data: DOMRect) => void,
): (element: HTMLElement | undefined) => void {
return element => {
const domRect = element?.getBoundingClientRect() || {
width: 0,
height: 0,
}
if ((domRect?.width ?? 0) !== 0 && (domRect?.height ?? 0) !== 0) {
callback(domRect as DOMRect)
}
}
}

View File

@ -14,7 +14,11 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
"jsx": "react-jsx",
"baseUrl": "./src",
"paths": {
"~/*": ["./*"]
}
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]

View File

@ -1,7 +1,13 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import * as path from "path";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()]
plugins: [react()],
resolve: {
alias: {
"~": path.resolve(__dirname, "src"),
}
}
})

1315
yarn.lock

File diff suppressed because it is too large Load Diff