added settings page
This commit is contained in:
@@ -36,4 +36,14 @@ CREATE TABLE IF NOT EXISTS products (
|
|||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (storage_location) REFERENCES storage_locations(uuid) ON DELETE CASCADE
|
FOREIGN KEY (storage_location) REFERENCES storage_locations(uuid) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS app_settings (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
value VARCHAR(500) DEFAULT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO app_settings (name, value) VALUES ("app-name", null), ("currency", null);
|
||||||
@@ -40,3 +40,35 @@ export const loginUser = async (username) => {
|
|||||||
return { code: "eu003" };
|
return { code: "eu003" };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updateSettings = async (payload) => {
|
||||||
|
const appName = payload["app-name"];
|
||||||
|
const currency = payload.currency;
|
||||||
|
|
||||||
|
const [result] = await pool.query(
|
||||||
|
`UPDATE app_settings
|
||||||
|
SET value = CASE name
|
||||||
|
WHEN "app-name" THEN ?
|
||||||
|
WHEN "currency" THEN ?
|
||||||
|
ELSE value
|
||||||
|
END
|
||||||
|
WHERE name IN ("app-name", "currency");`,
|
||||||
|
[appName, currency],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.affectedRows > 0) {
|
||||||
|
return { code: "su003" };
|
||||||
|
} else {
|
||||||
|
return { code: "eu004" };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getSettings = async () => {
|
||||||
|
const [result] = await pool.query(`SELECT * FROM app_settings;`);
|
||||||
|
|
||||||
|
if (result.length > 0) {
|
||||||
|
return { code: "su004", result };
|
||||||
|
} else {
|
||||||
|
return { code: "eu005" };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
import { authenticate, generateToken } from "../../services/tokenService.js";
|
import { authenticate, generateToken } from "../../services/tokenService.js";
|
||||||
import { findUser, loginUser } from "./database/users.database.js";
|
import {
|
||||||
|
findUser,
|
||||||
|
loginUser,
|
||||||
|
updateSettings,
|
||||||
|
getSettings,
|
||||||
|
} from "./database/users.database.js";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
@@ -9,6 +14,55 @@ router.post("/verify-token", authenticate, async (req, res) => {
|
|||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post("/update-app-settings", authenticate, async (req, res) => {
|
||||||
|
const appName = req.body.appName;
|
||||||
|
const currency = req.body.currency;
|
||||||
|
|
||||||
|
console.log(req.body);
|
||||||
|
|
||||||
|
const result = await updateSettings(req.body);
|
||||||
|
|
||||||
|
if (result.code === "su003") {
|
||||||
|
res.status(201).json({
|
||||||
|
success: true,
|
||||||
|
code: "su003",
|
||||||
|
data: result.data,
|
||||||
|
message: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.code === "eu004") {
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
code: "eu004",
|
||||||
|
data: null,
|
||||||
|
message: "Unexpected server error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/settings", authenticate, async (req, res) => {
|
||||||
|
const result = await getSettings();
|
||||||
|
|
||||||
|
if (result.code === "su004") {
|
||||||
|
res.status(201).json({
|
||||||
|
success: true,
|
||||||
|
code: "su004",
|
||||||
|
data: result.result,
|
||||||
|
message: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.code === "eu005") {
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
code: "eu005",
|
||||||
|
data: null,
|
||||||
|
message: "Unexpected server error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
router.post("/login", async (req, res) => {
|
router.post("/login", async (req, res) => {
|
||||||
const username = req.body.username;
|
const username = req.body.username;
|
||||||
const password = req.body.password;
|
const password = req.body.password;
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import { Button, Typography } from "@mui/joy";
|
|||||||
import InventoryIcon from "@mui/icons-material/Inventory";
|
import InventoryIcon from "@mui/icons-material/Inventory";
|
||||||
import AddBoxIcon from "@mui/icons-material/AddBox";
|
import AddBoxIcon from "@mui/icons-material/AddBox";
|
||||||
import StorageIcon from "@mui/icons-material/Storage";
|
import StorageIcon from "@mui/icons-material/Storage";
|
||||||
import AccountBoxIcon from "@mui/icons-material/AccountBox";
|
import SettingsIcon from "@mui/icons-material/Settings";
|
||||||
import { useNavigate, useMatchRoute } from "@tanstack/react-router";
|
import { useNavigate, useMatchRoute } from "@tanstack/react-router";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
export const Sidebar = () => {
|
export const Sidebar = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -30,7 +31,7 @@ export const Sidebar = () => {
|
|||||||
level="body-lg"
|
level="body-lg"
|
||||||
className="text-sm font-medium text-slate-500"
|
className="text-sm font-medium text-slate-500"
|
||||||
>
|
>
|
||||||
{t("app-subtitle")}
|
{Cookies.get("app-name") ? Cookies.get("app-name") : ""}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -60,12 +61,12 @@ export const Sidebar = () => {
|
|||||||
{t("storages")}
|
{t("storages")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => navigate({ to: "/app/profile" })}
|
onClick={() => navigate({ to: "/app/app-settings" })}
|
||||||
variant={variant("/app/profile")}
|
variant={variant("/app/app-settings")}
|
||||||
startDecorator={<AccountBoxIcon />}
|
startDecorator={<SettingsIcon />}
|
||||||
className={btnClass}
|
className={btnClass}
|
||||||
>
|
>
|
||||||
{t("profile")}
|
{t("settings")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -40,3 +40,8 @@ export interface AlertInterface {
|
|||||||
header: string;
|
header: string;
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SettingsIntf {
|
||||||
|
["app-name"]: string;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { useState } from "react";
|
|||||||
import { useForm } from "@tanstack/react-form";
|
import { useForm } from "@tanstack/react-form";
|
||||||
import { createProduct, getStorages } from "../utils/uxFncs";
|
import { createProduct, getStorages } from "../utils/uxFncs";
|
||||||
import type { ProductFormValues } from "../misc/interfaces";
|
import type { ProductFormValues } from "../misc/interfaces";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
export const AddProduct = () => {
|
export const AddProduct = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -205,7 +206,7 @@ export const AddProduct = () => {
|
|||||||
)}
|
)}
|
||||||
</form.Field>
|
</form.Field>
|
||||||
<Typography level="body-sm" className="text-slate-500">
|
<Typography level="body-sm" className="text-slate-500">
|
||||||
{t("currency")}
|
{Cookies.get("currency")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import { useQuery } from "@tanstack/react-query";
|
|||||||
import { getProducts } from "../utils/uxFncs";
|
import { getProducts } from "../utils/uxFncs";
|
||||||
import { visuallyHidden } from "@mui/utils";
|
import { visuallyHidden } from "@mui/utils";
|
||||||
import { formatDate } from "../utils/uxFncs";
|
import { formatDate } from "../utils/uxFncs";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
type Order = "asc" | "desc";
|
type Order = "asc" | "desc";
|
||||||
|
|
||||||
@@ -427,7 +428,7 @@ export const InventoryPage = () => {
|
|||||||
<td className="px-6 py-5">
|
<td className="px-6 py-5">
|
||||||
<Typography level="title-md">{row.price}</Typography>
|
<Typography level="title-md">{row.price}</Typography>
|
||||||
<Typography level="body-sm" className="text-slate-400">
|
<Typography level="body-sm" className="text-slate-400">
|
||||||
{t("currency")}
|
{Cookies.get("currency")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-5">
|
<td className="px-6 py-5">
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { Input, Button, CircularProgress } 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 { mutateSettings, fetchSettings } from "../utils/uxFncs";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
export const Settings = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: settings,
|
||||||
|
isPending: settingsPending,
|
||||||
|
isSuccess: settingsSuccess,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["settings"],
|
||||||
|
queryFn: fetchSettings,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
Cookies.set("app-name", settings?.data[0].value);
|
||||||
|
Cookies.set("currency", settings?.data[1].value);
|
||||||
|
}, [settingsSuccess]);
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
"app-name": settings?.data[0].value ?? "",
|
||||||
|
currency: settings?.data[1].value ?? "",
|
||||||
|
},
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
mutate(value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { mutate } = useMutation({
|
||||||
|
mutationFn: (values: SettingsIntf) => mutateSettings(values),
|
||||||
|
onSuccess() {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["settings"] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{settingsPending ? (
|
||||||
|
<CircularProgress />
|
||||||
|
) : (
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
form.handleSubmit();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<form.Field name="app-name">
|
||||||
|
{(field) => (
|
||||||
|
<Input
|
||||||
|
value={field.state.value}
|
||||||
|
onChange={(e) => field.handleChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</form.Field>
|
||||||
|
<form.Field name="currency">
|
||||||
|
{(field) => (
|
||||||
|
<Input
|
||||||
|
value={field.state.value}
|
||||||
|
onChange={(e) => field.handleChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</form.Field>
|
||||||
|
<Button type="submit">{t("submit")}</Button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -19,6 +19,7 @@ import { mutateProduct } from "../utils/uxFncs";
|
|||||||
import { toInputDate } from "../utils/uxFncs";
|
import { toInputDate } from "../utils/uxFncs";
|
||||||
import type { ProductFormValues } from "../misc/interfaces";
|
import type { ProductFormValues } from "../misc/interfaces";
|
||||||
import type { productDetailsInterface } from "../misc/interfaces";
|
import type { productDetailsInterface } from "../misc/interfaces";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
interface ViewProductProps {
|
interface ViewProductProps {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
@@ -256,7 +257,7 @@ export const ViewProduct = (props: ViewProductProps) => {
|
|||||||
)}
|
)}
|
||||||
</form.Field>
|
</form.Field>
|
||||||
<Typography level="body-sm" className="text-slate-500">
|
<Typography level="body-sm" className="text-slate-500">
|
||||||
{t("currency")}
|
{Cookies.get("currency")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import { Route as IndexRouteImport } from './routes/index'
|
|||||||
import { Route as AppHiddenLayoutRouteImport } from './routes/app/_hiddenLayout'
|
import { Route as AppHiddenLayoutRouteImport } from './routes/app/_hiddenLayout'
|
||||||
import { Route as AppHiddenLayoutViewProductRouteImport } from './routes/app/_hiddenLayout/view-product'
|
import { Route as AppHiddenLayoutViewProductRouteImport } from './routes/app/_hiddenLayout/view-product'
|
||||||
import { Route as AppHiddenLayoutStoragesRouteImport } from './routes/app/_hiddenLayout/storages'
|
import { Route as AppHiddenLayoutStoragesRouteImport } from './routes/app/_hiddenLayout/storages'
|
||||||
import { Route as AppHiddenLayoutProfileRouteImport } from './routes/app/_hiddenLayout/profile'
|
|
||||||
import { Route as AppHiddenLayoutInventoryRouteImport } from './routes/app/_hiddenLayout/inventory'
|
import { Route as AppHiddenLayoutInventoryRouteImport } from './routes/app/_hiddenLayout/inventory'
|
||||||
|
import { Route as AppHiddenLayoutAppSettingsRouteImport } from './routes/app/_hiddenLayout/app-settings'
|
||||||
import { Route as AppHiddenLayoutAddProductRouteImport } from './routes/app/_hiddenLayout/add-product'
|
import { Route as AppHiddenLayoutAddProductRouteImport } from './routes/app/_hiddenLayout/add-product'
|
||||||
|
|
||||||
const LoginRoute = LoginRouteImport.update({
|
const LoginRoute = LoginRouteImport.update({
|
||||||
@@ -44,17 +44,18 @@ const AppHiddenLayoutStoragesRoute = AppHiddenLayoutStoragesRouteImport.update({
|
|||||||
path: '/storages',
|
path: '/storages',
|
||||||
getParentRoute: () => AppHiddenLayoutRoute,
|
getParentRoute: () => AppHiddenLayoutRoute,
|
||||||
} as any)
|
} as any)
|
||||||
const AppHiddenLayoutProfileRoute = AppHiddenLayoutProfileRouteImport.update({
|
|
||||||
id: '/profile',
|
|
||||||
path: '/profile',
|
|
||||||
getParentRoute: () => AppHiddenLayoutRoute,
|
|
||||||
} as any)
|
|
||||||
const AppHiddenLayoutInventoryRoute =
|
const AppHiddenLayoutInventoryRoute =
|
||||||
AppHiddenLayoutInventoryRouteImport.update({
|
AppHiddenLayoutInventoryRouteImport.update({
|
||||||
id: '/inventory',
|
id: '/inventory',
|
||||||
path: '/inventory',
|
path: '/inventory',
|
||||||
getParentRoute: () => AppHiddenLayoutRoute,
|
getParentRoute: () => AppHiddenLayoutRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
const AppHiddenLayoutAppSettingsRoute =
|
||||||
|
AppHiddenLayoutAppSettingsRouteImport.update({
|
||||||
|
id: '/app-settings',
|
||||||
|
path: '/app-settings',
|
||||||
|
getParentRoute: () => AppHiddenLayoutRoute,
|
||||||
|
} as any)
|
||||||
const AppHiddenLayoutAddProductRoute =
|
const AppHiddenLayoutAddProductRoute =
|
||||||
AppHiddenLayoutAddProductRouteImport.update({
|
AppHiddenLayoutAddProductRouteImport.update({
|
||||||
id: '/add-product',
|
id: '/add-product',
|
||||||
@@ -67,8 +68,8 @@ export interface FileRoutesByFullPath {
|
|||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/app': typeof AppHiddenLayoutRouteWithChildren
|
'/app': typeof AppHiddenLayoutRouteWithChildren
|
||||||
'/app/add-product': typeof AppHiddenLayoutAddProductRoute
|
'/app/add-product': typeof AppHiddenLayoutAddProductRoute
|
||||||
|
'/app/app-settings': typeof AppHiddenLayoutAppSettingsRoute
|
||||||
'/app/inventory': typeof AppHiddenLayoutInventoryRoute
|
'/app/inventory': typeof AppHiddenLayoutInventoryRoute
|
||||||
'/app/profile': typeof AppHiddenLayoutProfileRoute
|
|
||||||
'/app/storages': typeof AppHiddenLayoutStoragesRoute
|
'/app/storages': typeof AppHiddenLayoutStoragesRoute
|
||||||
'/app/view-product': typeof AppHiddenLayoutViewProductRoute
|
'/app/view-product': typeof AppHiddenLayoutViewProductRoute
|
||||||
}
|
}
|
||||||
@@ -77,8 +78,8 @@ export interface FileRoutesByTo {
|
|||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/app': typeof AppHiddenLayoutRouteWithChildren
|
'/app': typeof AppHiddenLayoutRouteWithChildren
|
||||||
'/app/add-product': typeof AppHiddenLayoutAddProductRoute
|
'/app/add-product': typeof AppHiddenLayoutAddProductRoute
|
||||||
|
'/app/app-settings': typeof AppHiddenLayoutAppSettingsRoute
|
||||||
'/app/inventory': typeof AppHiddenLayoutInventoryRoute
|
'/app/inventory': typeof AppHiddenLayoutInventoryRoute
|
||||||
'/app/profile': typeof AppHiddenLayoutProfileRoute
|
|
||||||
'/app/storages': typeof AppHiddenLayoutStoragesRoute
|
'/app/storages': typeof AppHiddenLayoutStoragesRoute
|
||||||
'/app/view-product': typeof AppHiddenLayoutViewProductRoute
|
'/app/view-product': typeof AppHiddenLayoutViewProductRoute
|
||||||
}
|
}
|
||||||
@@ -88,8 +89,8 @@ export interface FileRoutesById {
|
|||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/app/_hiddenLayout': typeof AppHiddenLayoutRouteWithChildren
|
'/app/_hiddenLayout': typeof AppHiddenLayoutRouteWithChildren
|
||||||
'/app/_hiddenLayout/add-product': typeof AppHiddenLayoutAddProductRoute
|
'/app/_hiddenLayout/add-product': typeof AppHiddenLayoutAddProductRoute
|
||||||
|
'/app/_hiddenLayout/app-settings': typeof AppHiddenLayoutAppSettingsRoute
|
||||||
'/app/_hiddenLayout/inventory': typeof AppHiddenLayoutInventoryRoute
|
'/app/_hiddenLayout/inventory': typeof AppHiddenLayoutInventoryRoute
|
||||||
'/app/_hiddenLayout/profile': typeof AppHiddenLayoutProfileRoute
|
|
||||||
'/app/_hiddenLayout/storages': typeof AppHiddenLayoutStoragesRoute
|
'/app/_hiddenLayout/storages': typeof AppHiddenLayoutStoragesRoute
|
||||||
'/app/_hiddenLayout/view-product': typeof AppHiddenLayoutViewProductRoute
|
'/app/_hiddenLayout/view-product': typeof AppHiddenLayoutViewProductRoute
|
||||||
}
|
}
|
||||||
@@ -100,8 +101,8 @@ export interface FileRouteTypes {
|
|||||||
| '/login'
|
| '/login'
|
||||||
| '/app'
|
| '/app'
|
||||||
| '/app/add-product'
|
| '/app/add-product'
|
||||||
|
| '/app/app-settings'
|
||||||
| '/app/inventory'
|
| '/app/inventory'
|
||||||
| '/app/profile'
|
|
||||||
| '/app/storages'
|
| '/app/storages'
|
||||||
| '/app/view-product'
|
| '/app/view-product'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
@@ -110,8 +111,8 @@ export interface FileRouteTypes {
|
|||||||
| '/login'
|
| '/login'
|
||||||
| '/app'
|
| '/app'
|
||||||
| '/app/add-product'
|
| '/app/add-product'
|
||||||
|
| '/app/app-settings'
|
||||||
| '/app/inventory'
|
| '/app/inventory'
|
||||||
| '/app/profile'
|
|
||||||
| '/app/storages'
|
| '/app/storages'
|
||||||
| '/app/view-product'
|
| '/app/view-product'
|
||||||
id:
|
id:
|
||||||
@@ -120,8 +121,8 @@ export interface FileRouteTypes {
|
|||||||
| '/login'
|
| '/login'
|
||||||
| '/app/_hiddenLayout'
|
| '/app/_hiddenLayout'
|
||||||
| '/app/_hiddenLayout/add-product'
|
| '/app/_hiddenLayout/add-product'
|
||||||
|
| '/app/_hiddenLayout/app-settings'
|
||||||
| '/app/_hiddenLayout/inventory'
|
| '/app/_hiddenLayout/inventory'
|
||||||
| '/app/_hiddenLayout/profile'
|
|
||||||
| '/app/_hiddenLayout/storages'
|
| '/app/_hiddenLayout/storages'
|
||||||
| '/app/_hiddenLayout/view-product'
|
| '/app/_hiddenLayout/view-product'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
@@ -169,13 +170,6 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AppHiddenLayoutStoragesRouteImport
|
preLoaderRoute: typeof AppHiddenLayoutStoragesRouteImport
|
||||||
parentRoute: typeof AppHiddenLayoutRoute
|
parentRoute: typeof AppHiddenLayoutRoute
|
||||||
}
|
}
|
||||||
'/app/_hiddenLayout/profile': {
|
|
||||||
id: '/app/_hiddenLayout/profile'
|
|
||||||
path: '/profile'
|
|
||||||
fullPath: '/app/profile'
|
|
||||||
preLoaderRoute: typeof AppHiddenLayoutProfileRouteImport
|
|
||||||
parentRoute: typeof AppHiddenLayoutRoute
|
|
||||||
}
|
|
||||||
'/app/_hiddenLayout/inventory': {
|
'/app/_hiddenLayout/inventory': {
|
||||||
id: '/app/_hiddenLayout/inventory'
|
id: '/app/_hiddenLayout/inventory'
|
||||||
path: '/inventory'
|
path: '/inventory'
|
||||||
@@ -183,6 +177,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AppHiddenLayoutInventoryRouteImport
|
preLoaderRoute: typeof AppHiddenLayoutInventoryRouteImport
|
||||||
parentRoute: typeof AppHiddenLayoutRoute
|
parentRoute: typeof AppHiddenLayoutRoute
|
||||||
}
|
}
|
||||||
|
'/app/_hiddenLayout/app-settings': {
|
||||||
|
id: '/app/_hiddenLayout/app-settings'
|
||||||
|
path: '/app-settings'
|
||||||
|
fullPath: '/app/app-settings'
|
||||||
|
preLoaderRoute: typeof AppHiddenLayoutAppSettingsRouteImport
|
||||||
|
parentRoute: typeof AppHiddenLayoutRoute
|
||||||
|
}
|
||||||
'/app/_hiddenLayout/add-product': {
|
'/app/_hiddenLayout/add-product': {
|
||||||
id: '/app/_hiddenLayout/add-product'
|
id: '/app/_hiddenLayout/add-product'
|
||||||
path: '/add-product'
|
path: '/add-product'
|
||||||
@@ -195,16 +196,16 @@ declare module '@tanstack/react-router' {
|
|||||||
|
|
||||||
interface AppHiddenLayoutRouteChildren {
|
interface AppHiddenLayoutRouteChildren {
|
||||||
AppHiddenLayoutAddProductRoute: typeof AppHiddenLayoutAddProductRoute
|
AppHiddenLayoutAddProductRoute: typeof AppHiddenLayoutAddProductRoute
|
||||||
|
AppHiddenLayoutAppSettingsRoute: typeof AppHiddenLayoutAppSettingsRoute
|
||||||
AppHiddenLayoutInventoryRoute: typeof AppHiddenLayoutInventoryRoute
|
AppHiddenLayoutInventoryRoute: typeof AppHiddenLayoutInventoryRoute
|
||||||
AppHiddenLayoutProfileRoute: typeof AppHiddenLayoutProfileRoute
|
|
||||||
AppHiddenLayoutStoragesRoute: typeof AppHiddenLayoutStoragesRoute
|
AppHiddenLayoutStoragesRoute: typeof AppHiddenLayoutStoragesRoute
|
||||||
AppHiddenLayoutViewProductRoute: typeof AppHiddenLayoutViewProductRoute
|
AppHiddenLayoutViewProductRoute: typeof AppHiddenLayoutViewProductRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppHiddenLayoutRouteChildren: AppHiddenLayoutRouteChildren = {
|
const AppHiddenLayoutRouteChildren: AppHiddenLayoutRouteChildren = {
|
||||||
AppHiddenLayoutAddProductRoute: AppHiddenLayoutAddProductRoute,
|
AppHiddenLayoutAddProductRoute: AppHiddenLayoutAddProductRoute,
|
||||||
|
AppHiddenLayoutAppSettingsRoute: AppHiddenLayoutAppSettingsRoute,
|
||||||
AppHiddenLayoutInventoryRoute: AppHiddenLayoutInventoryRoute,
|
AppHiddenLayoutInventoryRoute: AppHiddenLayoutInventoryRoute,
|
||||||
AppHiddenLayoutProfileRoute: AppHiddenLayoutProfileRoute,
|
|
||||||
AppHiddenLayoutStoragesRoute: AppHiddenLayoutStoragesRoute,
|
AppHiddenLayoutStoragesRoute: AppHiddenLayoutStoragesRoute,
|
||||||
AppHiddenLayoutViewProductRoute: AppHiddenLayoutViewProductRoute,
|
AppHiddenLayoutViewProductRoute: AppHiddenLayoutViewProductRoute,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
import { Settings } from "../../../pages/Settings";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/app/_hiddenLayout/app-settings")({
|
||||||
|
component: RouteComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
return <Settings />;
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { createFileRoute } from '@tanstack/react-router'
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/app/_hiddenLayout/profile')({
|
|
||||||
component: RouteComponent,
|
|
||||||
})
|
|
||||||
|
|
||||||
function RouteComponent() {
|
|
||||||
return <div>Hello "/app/_hiddenLayout/profile"!</div>
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@ import { API_BASE } from "../config/api.config";
|
|||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import type { TFunction } from "i18next";
|
import type { TFunction } from "i18next";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
|
import { fetchSettings } from "./uxFncs";
|
||||||
|
|
||||||
export async function isAuthenticated() {
|
export async function isAuthenticated() {
|
||||||
if (Cookies.get("token")) {
|
if (Cookies.get("token")) {
|
||||||
@@ -39,10 +40,14 @@ export async function signInUser(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const response = await result.json();
|
const response = await result.json();
|
||||||
console.log(response);
|
|
||||||
|
|
||||||
if (result.status === 202) {
|
if (result.status === 202) {
|
||||||
Cookies.set("token", response.data.token);
|
Cookies.set("token", response.data.token);
|
||||||
|
|
||||||
|
const settings = await fetchSettings();
|
||||||
|
Cookies.set("app-name", settings?.data[0].value);
|
||||||
|
Cookies.set("currency", settings?.data[1].value);
|
||||||
|
|
||||||
return { ok: true as const };
|
return { ok: true as const };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Cookies from "js-cookie";
|
|||||||
import type {
|
import type {
|
||||||
NewStorage,
|
NewStorage,
|
||||||
ProductFormValues,
|
ProductFormValues,
|
||||||
|
SettingsIntf,
|
||||||
Storage,
|
Storage,
|
||||||
} from "../misc/interfaces";
|
} from "../misc/interfaces";
|
||||||
|
|
||||||
@@ -229,3 +230,46 @@ export const deleteStorage = async (uuid: string) => {
|
|||||||
return { success: true, code: response.code };
|
return { success: true, code: response.code };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mutateSettings = async (payload: SettingsIntf) => {
|
||||||
|
const result = await fetch(`${API_BASE}/users/update-app-settings`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Cookies.get("token") || ""}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await result.json();
|
||||||
|
|
||||||
|
if (response.code === "eu004") {
|
||||||
|
return { success: false, code: response.code };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.code === "su003") {
|
||||||
|
return { success: true, code: response.code };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchSettings = async () => {
|
||||||
|
const result = await fetch(`${API_BASE}/users/settings`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${Cookies.get("token") || ""}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await result.json();
|
||||||
|
|
||||||
|
if (response.code === "eu005") {
|
||||||
|
return { success: false, code: response.code };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.code === "su004") {
|
||||||
|
return { success: true, data: response.data, code: response.code };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user