refactor: edit tailwindcss classes and change code formatting, therefore added .prettierrc file
fix: frontend bug where the passwords won't be checked when the password is changed
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2
|
||||
}
|
||||
+12
-1
@@ -2,34 +2,45 @@ FROM node:22-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Workspace manifests (npm workspaces need these present)
|
||||
COPY package.json package-lock.json ./
|
||||
COPY backend/package.json backend/
|
||||
COPY frontend/package.json frontend/
|
||||
COPY shared/package.json shared/
|
||||
|
||||
# Install all deps for the monorepo (includes devDeps for building)
|
||||
RUN npm ci
|
||||
|
||||
# Copy sources required to build shared + backend
|
||||
COPY shared/ shared/
|
||||
COPY backend/ backend/
|
||||
|
||||
# Build shared (now produces dist/esm + dist/cjs + dist/types) and then backend
|
||||
RUN npm run build --workspace=shared
|
||||
RUN npm run build --workspace=backend
|
||||
|
||||
|
||||
FROM node:22-alpine AS runner
|
||||
|
||||
ENV NODE_ENV=production
|
||||
WORKDIR /app
|
||||
|
||||
# Workspace manifests again (so npm can install prod deps for backend + shared)
|
||||
COPY package.json package-lock.json ./
|
||||
COPY backend/package.json backend/
|
||||
COPY frontend/package.json frontend/
|
||||
COPY shared/package.json shared/
|
||||
|
||||
# Install prod deps only
|
||||
RUN npm ci --omit=dev
|
||||
|
||||
# Copy runtime artifacts
|
||||
COPY --from=builder /app/backend/dist backend/dist
|
||||
COPY --from=builder /app/backend/database.scheme.sql backend/
|
||||
COPY --from=builder /app/backend/database.scheme.sql backend/database.scheme.sql
|
||||
|
||||
# Copy the full shared dist output (esm/cjs/types)
|
||||
COPY --from=builder /app/shared/dist shared/dist
|
||||
COPY shared/package.json shared/package.json
|
||||
|
||||
EXPOSE 8004
|
||||
WORKDIR /app/backend
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import mysql, {type ResultSetHeader, type RowDataPacket} from "mysql2/promise";
|
||||
import mysql, {
|
||||
type ResultSetHeader,
|
||||
type RowDataPacket,
|
||||
} from "mysql2/promise";
|
||||
import dotenv from "dotenv";
|
||||
import { returnErrorCode } from "../../../services/helperFuncs.js";
|
||||
import { PRODUCT_ERROR_CODE } from "@stockhome/shared";
|
||||
@@ -20,12 +23,22 @@ export const newProduct = async (
|
||||
storage_location: string,
|
||||
expiry_date: string,
|
||||
bottling_date: string,
|
||||
): Promise<boolean | { success: boolean; code: string; data: null; message: string }> => {
|
||||
): Promise<
|
||||
boolean | { success: boolean; code: string; data: null; message: string }
|
||||
> => {
|
||||
const newPrice = price !== "" ? price : null;
|
||||
|
||||
const [result] = await pool.query<ResultSetHeader>(
|
||||
"INSERT INTO products (name, description, price, amount, storage_location, expiry_date, bottling_date) VALUES (?, ?, ?, ?, UUID_TO_BIN(?), ?, ?)",
|
||||
[name, description, newPrice, amount, storage_location, expiry_date, bottling_date],
|
||||
[
|
||||
name,
|
||||
description,
|
||||
newPrice,
|
||||
amount,
|
||||
storage_location,
|
||||
expiry_date,
|
||||
bottling_date,
|
||||
],
|
||||
);
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
@@ -182,7 +195,6 @@ export const deleteProduct = async (uuid: string) => {
|
||||
data: null,
|
||||
message: "Product deleted successfully.",
|
||||
};
|
||||
;
|
||||
}
|
||||
|
||||
return returnErrorCode(PRODUCT_ERROR_CODE.PRODUCT_NOT_DELETED);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import mysql, {type ResultSetHeader, type RowDataPacket} from "mysql2/promise";
|
||||
import mysql, {
|
||||
type ResultSetHeader,
|
||||
type RowDataPacket,
|
||||
} from "mysql2/promise";
|
||||
import dotenv from "dotenv";
|
||||
import { STORAGE_ERROR_CODE } from "@stockhome/shared";
|
||||
import { returnErrorCode } from "../../../services/helperFuncs.js";
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import mysql, {type ResultSetHeader, type RowDataPacket} from "mysql2/promise";
|
||||
import mysql, {
|
||||
type ResultSetHeader,
|
||||
type RowDataPacket,
|
||||
} from "mysql2/promise";
|
||||
import dotenv from "dotenv";
|
||||
import { GENERAL_ERROR_CODE, USER_ERROR_CODE } from "@stockhome/shared";
|
||||
import { returnErrorCode } from "../../../services/helperFuncs.js";
|
||||
@@ -127,6 +130,6 @@ export const changePassword = async (
|
||||
message: "Successfully fetched settings.",
|
||||
};
|
||||
} else {
|
||||
return returnErrorCode(GENERAL_ERROR_CODE.UNEXPECTED_SERVER_ERROR);
|
||||
return returnErrorCode(USER_ERROR_CODE.PASSWORD_CHANGE_FAILED);
|
||||
}
|
||||
};
|
||||
@@ -1,7 +1,12 @@
|
||||
import express from "express";
|
||||
import dotenv from "dotenv";
|
||||
import { authenticate } from "../../services/tokenService";
|
||||
import {allStorages, deleteStorage, newStorage, updateStorage,} from "./database/storage.database";
|
||||
import {
|
||||
allStorages,
|
||||
deleteStorage,
|
||||
newStorage,
|
||||
updateStorage,
|
||||
} from "./database/storage.database";
|
||||
import { GENERAL_ERROR_CODE, STORAGE_ERROR_CODE } from "@stockhome/shared";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import express from "express";
|
||||
import dotenv from "dotenv";
|
||||
import { authenticate, generateToken } from "../../services/tokenService";
|
||||
import {changePassword, findUser, getSettings, loginUser, updateSettings,} from "./database/users.database";
|
||||
import {
|
||||
changePassword,
|
||||
findUser,
|
||||
getSettings,
|
||||
loginUser,
|
||||
updateSettings,
|
||||
} from "./database/users.database";
|
||||
import { GENERAL_ERROR_CODE, USER_ERROR_CODE } from "@stockhome/shared";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
+6
-3
@@ -3,8 +3,7 @@ import express from "express";
|
||||
import cors from "cors";
|
||||
import dotenv from "dotenv";
|
||||
import mysql, { type ResultSetHeader, type RowDataPacket } from "mysql2";
|
||||
import {readFile} from "fs/promises";
|
||||
// frontend routes
|
||||
import { readFile } from "fs/promises"; // frontend routes
|
||||
import userRouter from "./routes/app/users.route";
|
||||
import productRouter from "./routes/app/products.route";
|
||||
import storageRouter from "./routes/app/storage.route";
|
||||
@@ -50,7 +49,11 @@ const runStartup = async (port: number) => {
|
||||
);
|
||||
firstStartupValue = firstResponse[0]?.value ?? null;
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof Error && (err as NodeJS.ErrnoException & { code?: string }).code !== "ER_NO_SUCH_TABLE") {
|
||||
if (
|
||||
err instanceof Error &&
|
||||
(err as NodeJS.ErrnoException & { code?: string }).code !==
|
||||
"ER_NO_SUCH_TABLE"
|
||||
) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ export const returnErrorCode = (errorKey: ErrorCode) => {
|
||||
success: false,
|
||||
code: errorKey[0],
|
||||
data: null,
|
||||
message: errorKey[1]
|
||||
}
|
||||
message: errorKey[1],
|
||||
};
|
||||
};
|
||||
@@ -23,7 +23,11 @@ export async function generateToken(payload: AuthTokenPayload) {
|
||||
.sign(secret);
|
||||
}
|
||||
|
||||
export async function authenticate(req: Request, res: Response, next: NextFunction) {
|
||||
export async function authenticate(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
const authHeader = req.headers["authorization"];
|
||||
const token = authHeader && authHeader.split(" ")[1];
|
||||
|
||||
|
||||
@@ -9,17 +9,13 @@
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"ignoreDeprecations": "6.0",
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"types": ["node"],
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"./**/*.ts"
|
||||
],
|
||||
"include": ["./**/*.ts"],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
|
||||
+12
-12
@@ -1,29 +1,29 @@
|
||||
import {defineConfig} from 'vite'
|
||||
import path from 'path'
|
||||
import {dirname} from "node:path"
|
||||
import {fileURLToPath} from "node:url"
|
||||
import { defineConfig } from "vite";
|
||||
import path from "path";
|
||||
import { dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
export default defineConfig({
|
||||
root: 'src',
|
||||
root: "src",
|
||||
build: {
|
||||
outDir: '../dist',
|
||||
outDir: "../dist",
|
||||
emptyOutDir: true,
|
||||
sourcemap: true,
|
||||
minify: 'esbuild',
|
||||
assetsDir: 'assets',
|
||||
minify: "esbuild",
|
||||
assetsDir: "assets",
|
||||
rollupOptions: {
|
||||
input: path.resolve(__dirname, 'src/index.html'),
|
||||
input: path.resolve(__dirname, "src/index.html"),
|
||||
output: {
|
||||
assetFileNames: 'assets/[name]-[hash][extname]',
|
||||
assetFileNames: "assets/[name]-[hash][extname]",
|
||||
},
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
"@": path.resolve(__dirname, "src"),
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { Input, Button, Alert } from "@mui/joy";
|
||||
import { Alert, Button, Input } from "@mui/joy";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { signInUser } from "../utils/api/auth";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@@ -9,7 +9,7 @@ import ExitToAppIcon from "@mui/icons-material/ExitToApp";
|
||||
import TranslateIcon from "@mui/icons-material/Translate";
|
||||
import MenuIcon from "@mui/icons-material/Menu";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import { useNavigate, useMatchRoute } from "@tanstack/react-router";
|
||||
import { useMatchRoute, useNavigate } from "@tanstack/react-router";
|
||||
import Cookies from "js-cookie";
|
||||
import { changeTranslation } from "../utils/uxFncs";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useQueryClient, useMutation } from "@tanstack/react-query";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { deleteStorage, updateStorage } from "../utils/api/storages";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useStore } from "@tanstack/react-store";
|
||||
import { Input, Button } from "@mui/joy";
|
||||
import { Button, Input } from "@mui/joy";
|
||||
import type { Storage } from "../misc/interfaces";
|
||||
import { formatDate } from "../utils/uxFncs";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Input,
|
||||
Modal,
|
||||
ModalDialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
Stack,
|
||||
Input,
|
||||
Button,
|
||||
Alert,
|
||||
} from "@mui/joy";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { NewStorage, AlertInterface } from "../../misc/interfaces";
|
||||
import type { AlertInterface, NewStorage } from "../../misc/interfaces";
|
||||
import { mutateNewStorage } from "../../utils/api/storages";
|
||||
import { useState } from "react";
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
DialogTitle,
|
||||
Input,
|
||||
Modal,
|
||||
ModalDialog,
|
||||
DialogTitle,
|
||||
Stack,
|
||||
Input,
|
||||
Button,
|
||||
Alert,
|
||||
} from "@mui/joy";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { ChangePasswordIntf, AlertInterface } from "../../misc/interfaces";
|
||||
import type { AlertInterface, ChangePasswordIntf } from "../../misc/interfaces";
|
||||
import { mutatePassword } from "../../utils/api/auth";
|
||||
import { useState } from "react";
|
||||
import { USER_ERROR_CODE } from "@stockhome/shared";
|
||||
|
||||
interface ChangePasswordProps {
|
||||
isOpen: boolean;
|
||||
setOpen: (value: boolean) => void;
|
||||
alert: (alert: AlertInterface) => void;
|
||||
}
|
||||
|
||||
export const ChangePasswordModal = (props: ChangePasswordProps) => {
|
||||
@@ -35,7 +37,18 @@ export const ChangePasswordModal = (props: ChangePasswordProps) => {
|
||||
newPasswordRep: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
console.log(value);
|
||||
|
||||
if (value.newPassword === value.newPasswordRep) {
|
||||
mutate(value);
|
||||
} else {
|
||||
setAlert({
|
||||
isAlert: true,
|
||||
type: "danger",
|
||||
header: t("error"),
|
||||
text: t(USER_ERROR_CODE.PASSWORDS_NOT_MATCHED[0]),
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -50,6 +63,21 @@ export const ChangePasswordModal = (props: ChangePasswordProps) => {
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
// Sets the success alert in the settings page via component props
|
||||
props.alert({
|
||||
isAlert: true,
|
||||
type: "success",
|
||||
header: t("success"),
|
||||
text: t("SU005"),
|
||||
});
|
||||
|
||||
// Sets the success alert locally (in the modal itself)
|
||||
setAlert({
|
||||
isAlert: true,
|
||||
type: "success",
|
||||
header: t("success"),
|
||||
text: t("SU005"),
|
||||
});
|
||||
props.setOpen(false);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -16,8 +16,8 @@ import { useForm } from "@tanstack/react-form";
|
||||
import { createProduct } from "../utils/api/products";
|
||||
import { getStorages } from "../utils/api/storages";
|
||||
import type {
|
||||
ProductFormValues,
|
||||
AlertInterface,
|
||||
ProductFormValues,
|
||||
Storage,
|
||||
} from "../misc/interfaces";
|
||||
import type { ApiError } from "../utils/api/apiError";
|
||||
@@ -272,10 +272,11 @@ export const AddProduct = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div className="flex gap-3 items-center">
|
||||
<Typography level="body-sm" className="text-slate-500">
|
||||
{t("product-details")}
|
||||
</Typography>
|
||||
<div className="grow"></div>
|
||||
<Button
|
||||
type="submit"
|
||||
loading={isPending}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
Typography,
|
||||
Alert,
|
||||
Avatar,
|
||||
Button,
|
||||
Checkbox,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
Sheet,
|
||||
Table,
|
||||
Avatar,
|
||||
Chip,
|
||||
Checkbox,
|
||||
Alert,
|
||||
Typography,
|
||||
} from "@mui/joy";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -17,8 +17,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { deleteSelectedProducts, getProducts } from "../utils/api/products";
|
||||
import { formatDate } from "../utils/uxFncs";
|
||||
import Cookies from "js-cookie";
|
||||
import type { ProductRow } from "../misc/interfaces";
|
||||
import type { AlertInterface } from "../misc/interfaces";
|
||||
import type { AlertInterface, ProductRow } from "../misc/interfaces";
|
||||
import type { ApiError } from "../utils/api/apiError";
|
||||
|
||||
export const InventoryPage = () => {
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { getStorages } from "../utils/api/storages.ts";
|
||||
import {
|
||||
CircularProgress,
|
||||
Typography,
|
||||
Select,
|
||||
Option,
|
||||
Input,
|
||||
Alert,
|
||||
Box,
|
||||
Button,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
Divider,
|
||||
Box,
|
||||
Alert,
|
||||
Input,
|
||||
Option,
|
||||
Select,
|
||||
Typography,
|
||||
} from "@mui/joy";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { mutateProduct, getProductDetails } from "../utils/api/products.ts";
|
||||
import { getProductDetails, mutateProduct } from "../utils/api/products.ts";
|
||||
import { toInputDate } from "../utils/uxFncs";
|
||||
import type {
|
||||
ProductFormValues,
|
||||
productDetailsInterface,
|
||||
AlertInterface,
|
||||
productDetailsInterface,
|
||||
ProductFormValues,
|
||||
Storage,
|
||||
} from "../misc/interfaces";
|
||||
import type { ApiError } from "../utils/api/apiError";
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
import {
|
||||
Input,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Typography,
|
||||
Sheet,
|
||||
Chip,
|
||||
Divider,
|
||||
Alert,
|
||||
Button,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
Divider,
|
||||
Input,
|
||||
Sheet,
|
||||
Typography,
|
||||
} from "@mui/joy";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import Cookies from "js-cookie";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { SettingsIntf } from "../misc/interfaces";
|
||||
import type { AlertInterface } from "../misc/interfaces";
|
||||
import type { AlertInterface, SettingsIntf } from "../misc/interfaces";
|
||||
import type { ApiError } from "../utils/api/apiError";
|
||||
import { mutateSettings, fetchSettings } from "../utils/api/settings";
|
||||
import { fetchSettings, mutateSettings } from "../utils/api/settings";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ChangePasswordModal } from "../components/modals/ChangePasswordModal";
|
||||
|
||||
@@ -90,7 +89,7 @@ export const Settings = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<ChangePasswordModal isOpen={modal} setOpen={setModal} />
|
||||
<ChangePasswordModal alert={setAlert} isOpen={modal} setOpen={setModal} />
|
||||
<div className="space-y-6">
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<div className="space-y-1">
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getStorages } from "../utils/api/storages";
|
||||
import {
|
||||
Sheet,
|
||||
Table,
|
||||
Alert,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Sheet,
|
||||
Table,
|
||||
Typography,
|
||||
Alert,
|
||||
} from "@mui/joy";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { Storage } from "../misc/interfaces";
|
||||
import type { AlertInterface } from "../misc/interfaces";
|
||||
import type { AlertInterface, Storage } from "../misc/interfaces";
|
||||
import type { ApiError } from "../utils/api/apiError";
|
||||
import { StorageRow } from "../components/StorageRow";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { getStorages } from "../utils/api/storages.ts";
|
||||
import {
|
||||
CircularProgress,
|
||||
Typography,
|
||||
Select,
|
||||
Option,
|
||||
Input,
|
||||
Alert,
|
||||
Box,
|
||||
Button,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
Divider,
|
||||
Box,
|
||||
Alert,
|
||||
Input,
|
||||
Option,
|
||||
Select,
|
||||
Typography,
|
||||
} from "@mui/joy";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { mutateProduct, getProductDetails } from "../utils/api/products.ts";
|
||||
import { getProductDetails, mutateProduct } from "../utils/api/products.ts";
|
||||
import { toInputDate } from "../utils/uxFncs";
|
||||
import type {
|
||||
ProductFormValues,
|
||||
productDetailsInterface,
|
||||
AlertInterface,
|
||||
productDetailsInterface,
|
||||
ProductFormValues,
|
||||
Storage,
|
||||
} from "../misc/interfaces";
|
||||
import type { ApiError } from "../utils/api/apiError";
|
||||
@@ -342,10 +342,12 @@ export const ViewProduct = (props: ViewProductProps) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<div className="flex gap-3 items-center">
|
||||
<Typography level="body-sm" className="text-slate-500">
|
||||
{t("product-details")}
|
||||
</Typography>
|
||||
<div className="grow"></div>
|
||||
<Button
|
||||
startDecorator={<QrCodeIcon />}
|
||||
loading={isPending}
|
||||
@@ -364,6 +366,8 @@ export const ViewProduct = (props: ViewProductProps) => {
|
||||
{t("save")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{alert.isAlert && (
|
||||
<Alert
|
||||
color={alert.type}
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"error": "Fehler",
|
||||
"success": "Erfolg",
|
||||
"submit": "Absenden",
|
||||
"SU005": "Das Passwort wurde erfolgreich geändert!",
|
||||
"EG001": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.",
|
||||
"EU001": "Falscher Benutzername oder Passwort!",
|
||||
"EU002": "Ihr Konto wurde deaktiviert. Bitte wenden Sie sich an einen Administrator.",
|
||||
@@ -67,6 +68,7 @@
|
||||
"EU007": "Passwort konnte nicht geändert werden. Bitte versuchen Sie es erneut.",
|
||||
"EU008": "Ihre Einstellungen konnten nicht gespeichert werden. Bitte versuchen Sie es erneut.",
|
||||
"EU009": "Ihre Einstellungen konnten nicht geladen werden. Bitte versuchen Sie es erneut.",
|
||||
"EU010": "Sie müssen Ihr neues Passwort zweimal korrekt eingeben.",
|
||||
"ES001": "Bitte füllen Sie alle erforderlichen Felder für den Lagerort aus.",
|
||||
"ES002": "Einige erforderliche Lagerinformationen fehlen. Bitte überprüfen Sie Ihre Eingabe.",
|
||||
"ES003": "Der Lagerort konnte nicht aktualisiert werden. Bitte versuchen Sie es erneut.",
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"error": "Error",
|
||||
"success": "Success",
|
||||
"submit": "Submit",
|
||||
"SU005": "Your password is updated successfully!",
|
||||
"EG001": "An unexpected error occurred. Please try again later.",
|
||||
"EU001": "Wrong username or password!",
|
||||
"EU002": "Your account has been deactivated. Please contact an administrator.",
|
||||
@@ -67,6 +68,7 @@
|
||||
"EU007": "Failed to change your password. Please try again.",
|
||||
"EU008": "Your settings could not be saved. Please try again.",
|
||||
"EU009": "Your settings could not be loaded. Please try again.",
|
||||
"EU010": "You must enter your new password twice correctly.",
|
||||
"ES001": "Please fill in all required fields for the storage location.",
|
||||
"ES002": "Some required storage information is missing. Please check your input.",
|
||||
"ES003": "The storage location could not be updated. Please try again.",
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
+5
-2
@@ -9,12 +9,15 @@
|
||||
"version": "0.1.0-dev",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"build:shared": "npm run build --workspace=@stockhome/shared",
|
||||
"build:backend": "npm run build --workspace=backend",
|
||||
"build:frontend": "npm run build --workspace=frontend",
|
||||
"dev:frontend": "npm run dev --workspace=frontend",
|
||||
"dev:backend": "npm run dev --workspace=backend",
|
||||
"dev:backend": "npm run build:shared && npm run dev --workspace=backend",
|
||||
"dev:docker": "docker compose -f docker-compose.dev.yml up -d --wait",
|
||||
"dev": "npm run dev:docker && concurrently --kill-others \"npm:dev:frontend\" \"npm:dev:backend\"",
|
||||
"dev:stop": "docker compose -f docker-compose.dev.yml down",
|
||||
"buildProd": "npm run build --workspace=frontend && npm run build --workspace=backend"
|
||||
"buildProd": "npm run build:shared && npm run build:backend && npm run build:frontend"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
+12
-4
@@ -2,14 +2,22 @@
|
||||
"name": "@stockhome/shared",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "commonjs",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"prebuild": "barrelsby --directory src --delete --single",
|
||||
"build": "tsc -b",
|
||||
"build:esm": "tsc -p tsconfig.esm.json",
|
||||
"build:cjs": "tsc -p tsconfig.cjs.json",
|
||||
"build": "npm run prebuild && npm run build:esm && npm run build:cjs",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"main": "./dist/src/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"import": "./dist/esm/index.js",
|
||||
"require": "./dist/cjs/index.js"
|
||||
}
|
||||
},
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"devDependencies": {
|
||||
"barrelsby": "^2.8.1",
|
||||
"typescript": "~6.0.2"
|
||||
|
||||
@@ -5,18 +5,25 @@ export const GENERAL_ERROR_CODE = {
|
||||
export const USER_ERROR_CODE = {
|
||||
WRONG_USERNAME_PASSWORD: ["EU001", "Username or password is wrong"],
|
||||
USER_IS_DEACTIVATED: ["EU002", "User is deactivated"],
|
||||
INVALID_REQUEST_BODY: ["EU003", "Invalid request body. Username and password are required."],
|
||||
INVALID_REQUEST_BODY: [
|
||||
"EU003",
|
||||
"Invalid request body. Username and password are required.",
|
||||
],
|
||||
INVALID_PARAMETERS: ["EU004", "Invalid or missing parameters."],
|
||||
TOKEN_GENERATION_FAILED: ["EU005", "Failed to generate user token."],
|
||||
LOGIN_FAILED: ["EU006", "Failed to log in user."],
|
||||
PASSWORD_CHANGE_FAILED: ["EU007", "Failed to change password."],
|
||||
SETTINGS_NOT_UPDATED: ["EU008", "Settings could not be updated."],
|
||||
SETTINGS_NOT_FOUND: ["EU009", "Settings could not be retrieved."],
|
||||
PASSWORDS_NOT_MATCHED: ["EU010", "The two passwords are not matching."],
|
||||
} as const;
|
||||
|
||||
export const STORAGE_ERROR_CODE = {
|
||||
INVALID_REQUEST_BODY: ["ES001", "Invalid request body"],
|
||||
INVALID_PARAMETERS: ["ES002", "Parameter storageUUID or/and parameter values are/is missing."],
|
||||
INVALID_PARAMETERS: [
|
||||
"ES002",
|
||||
"Parameter storageUUID or/and parameter values are/is missing.",
|
||||
],
|
||||
STORAGE_NOT_UPDATED: ["ES003", "Storage is not updated."],
|
||||
STORAGE_NOT_DELETED: ["ES004", "Storage is not deleted."],
|
||||
NO_STORAGE_LOCATIONS_FOUND: ["ES005", "No storage locations found"],
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"target": "ES2022",
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/cjs",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "Node",
|
||||
"declaration": false,
|
||||
"declarationMap": false,
|
||||
"ignoreDeprecations": "6.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outDir": "./dist/esm",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"declaration": true,
|
||||
"declarationDir": "./dist/types",
|
||||
"declarationMap": true
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,5 @@
|
||||
"skipLibCheck": true,
|
||||
"ignoreDeprecations": "6.0"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user