thejagstudio commited on
Commit
49d3082
1 Parent(s): 155fa5d

Upload 39 files

Browse files
vafront/.eslintrc.cjs ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ root: true,
3
+ env: { browser: true, es2020: true },
4
+ extends: [
5
+ 'eslint:recommended',
6
+ 'plugin:react/recommended',
7
+ 'plugin:react/jsx-runtime',
8
+ 'plugin:react-hooks/recommended',
9
+ ],
10
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
11
+ parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
12
+ settings: { react: { version: '18.2' } },
13
+ plugins: ['react-refresh'],
14
+ rules: {
15
+ 'react/jsx-no-target-blank': 'off',
16
+ 'react-refresh/only-export-components': [
17
+ 'warn',
18
+ { allowConstantExport: true },
19
+ ],
20
+ },
21
+ }
vafront/.gitignore ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+
15
+ # Editor directories and files
16
+ .vscode/*
17
+ !.vscode/extensions.json
18
+ .idea
19
+ .DS_Store
20
+ *.suo
21
+ *.ntvs*
22
+ *.njsproj
23
+ *.sln
24
+ *.sw?
vafront/README.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # React + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
vafront/dist/Symbol.svg ADDED
vafront/dist/assets/index-DY9R8Td0.js ADDED
The diff for this file is too large to render. See raw diff
 
vafront/dist/assets/index-DyhO2yRi.css ADDED
The diff for this file is too large to render. See raw diff
 
vafront/dist/blackLogo.svg ADDED
vafront/dist/index.html ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/png" href="/symbol.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>VoiceAssist</title>
8
+ <script type="module" crossorigin src="/assets/index-DY9R8Td0.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-DyhO2yRi.css">
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
vafront/dist/symbol.png ADDED
vafront/dist/vite.svg ADDED
vafront/dist/whiteLogo.svg ADDED
vafront/index.html ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/png" href="/symbol.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>VoiceAssist</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.jsx"></script>
12
+ </body>
13
+ </html>
vafront/package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
vafront/package.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "vafront",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "@material-tailwind/react": "^2.1.9",
14
+ "artyom.js": "^1.0.6",
15
+ "jotai": "^2.8.0",
16
+ "react": "^18.2.0",
17
+ "react-dom": "^18.2.0",
18
+ "react-router-dom": "^6.23.1"
19
+ },
20
+ "devDependencies": {
21
+ "@types/react": "^18.2.66",
22
+ "@types/react-dom": "^18.2.22",
23
+ "@vitejs/plugin-react": "^4.2.1",
24
+ "autoprefixer": "^10.4.19",
25
+ "eslint": "^8.57.0",
26
+ "eslint-plugin-react": "^7.34.1",
27
+ "eslint-plugin-react-hooks": "^4.6.0",
28
+ "eslint-plugin-react-refresh": "^0.4.6",
29
+ "postcss": "^8.4.38",
30
+ "tailwindcss": "^3.4.3",
31
+ "vite": "^5.2.0"
32
+ }
33
+ }
vafront/postcss.config.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
vafront/public/Symbol.svg ADDED
vafront/public/blackLogo.svg ADDED
vafront/public/symbol.png ADDED
vafront/public/vite.svg ADDED
vafront/public/whiteLogo.svg ADDED
vafront/src/App.jsx ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useEffect, useState } from "react";
2
+ import { useAtom } from "jotai";
3
+ import { VoiceAssistAtom, CurrentRollAtom, CurrentGRNAtom, TranscribeAtom, rollsAtom, grnsAtom, searchAtom } from "./Variables";
4
+ import { Routes, Route, useNavigate } from "react-router-dom";
5
+ import { CusNavbar } from "./Components/CusNavbar";
6
+ import RollCard from "./Components/RollCard";
7
+ import HomePage from "./Pages/HomePage";
8
+ import ErrorPage from "./Pages/ErrorPage";
9
+ import AddRollPage from "./Pages/AddRollPage";
10
+ import TranscribePage from "./Pages/TranscribePage";
11
+ import RollDetailPage from "./Pages/RollDetailPage";
12
+ import GRNCard from "./Components/GRNCard";
13
+ import GRNDetailPage from "./Pages/GRNDetailPage";
14
+
15
+ function App() {
16
+ const [search, setSearch] = useAtom(searchAtom);
17
+ const [rolls, setRolls] = useAtom(rollsAtom);
18
+ const [grns, setGrns] = useAtom(grnsAtom);
19
+ const [voiceAssist, setVoiceAssist] = useAtom(VoiceAssistAtom);
20
+ const [currentRoll, setCurrentRoll] = useAtom(CurrentRollAtom);
21
+ const [currentGRN, setCurrentGRN] = useAtom(CurrentGRNAtom);
22
+ const [transcribe, setTranscribe] = useAtom(TranscribeAtom);
23
+ const [sidebar, setSidebar] = useState(true);
24
+ const navigate = useNavigate();
25
+ useEffect(() => {
26
+ if (localStorage.getItem("currentGRN")) {
27
+ setCurrentGRN(JSON.parse(localStorage.getItem("currentGRN")));
28
+ }
29
+ fetch("/api/grns")
30
+ .then((res) => res.json())
31
+ .then((data) => {
32
+ setGrns(data["data"]);
33
+ voiceAssist.on(["open *", "grn *", "open grn *"], true).then((i, wildcard) => {
34
+ wildcard = wildcard.replace(/\s/g, "").replace(/-/g, "");
35
+ let found = false;
36
+ for (let index = 0; index < data["data"].length; index++) {
37
+ if (data["data"][index].GRN.toLowerCase() == wildcard.toLowerCase()) {
38
+ setCurrentGRN(data["data"][index]);
39
+ localStorage.setItem("currentGRN", JSON.stringify(data["data"][index]));
40
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "open GRN " + wildcard, isCommand: true }]);
41
+ navigate("/grn");
42
+ found = true;
43
+ }
44
+ }
45
+ if (!found) {
46
+ voiceAssist.say("No GRN found with that Number");
47
+ }
48
+ });
49
+ })
50
+ .catch((err) => console.error(err));
51
+ voiceAssist.emptyCommands();
52
+ voiceAssist.on(["search *"], true).then((i, wildcard) => {
53
+ wildcard = wildcard.replace(/ /g, "");
54
+ setSearch(wildcard);
55
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "search " + wildcard, isCommand: true }]);
56
+ });
57
+ voiceAssist.on(["transcribe"]).then((i) => {
58
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "transcribe", isCommand: true }]);
59
+ navigate("/transcribe");
60
+ });
61
+ voiceAssist.on(["home", "go to home"]).then((i) => {
62
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "home", isCommand: true }]);
63
+ navigate("/");
64
+ });
65
+ voiceAssist.on(["refresh"]).then((i) => {
66
+ window.location.reload();
67
+ });
68
+ voiceAssist.fatality();
69
+ setTimeout(() => {
70
+ voiceAssist
71
+ .initialize({
72
+ lang: "en-US",
73
+ continuous: true,
74
+ soundex: true,
75
+ debug: true,
76
+ executionKeyword: "and do it now",
77
+ listen: true,
78
+ name: "",
79
+ speed: 1.2,
80
+ // mode:"quick"
81
+ })
82
+ .then(() => {
83
+ console.log("Artyom has been succesfully initialized");
84
+ })
85
+ .catch((err) => {
86
+ console.error("Artyom couldn't be initialized: ", err);
87
+ });
88
+ }, 250);
89
+ voiceAssist.redirectRecognizedTextOutput((recognized, isFinal) => {
90
+ if (isFinal && recognized != "") {
91
+ setTranscribe((prev) => [...prev, { msg: recognized, isCommand: false }]);
92
+ }
93
+ });
94
+ }, []);
95
+ return (
96
+ <div className="flex flex-col h-screen w-full overflow-hidden relative">
97
+ {transcribe.length > 0 && (
98
+ <div className="z-50 max-w-[25%] absolute bottom-5 right-10 flex flex-col items-end gap-2">
99
+ {transcribe.map((item, index) => {
100
+ if (transcribe.length - index > 4) return null;
101
+ return (
102
+ <div key={index} className={"relative w-fit max-w-full text-white rounded-lg rounded-br-none p-3 px-4 transition-all duration-700 origin-bottom-right " + (item?.isCommand ? "bg-orange-500 " : "bg-primary-500 ")} style={{ opacity: transcribe.length - index < 4 ? 1.25 - (transcribe.length - index) * 0.25 : 0, transform: transcribe.length - index == 4 ? "translate(200px,0px)" : "scale(1)" }}>
103
+ <p>{item?.msg}</p>
104
+ <svg className={"absolute translate-x-1/2 translate-y-[2.5px] bottom-0 right-0 h-5 w-5 scale-x-150 " + (item?.isCommand ? "text-orange-500" : "text-primary-500")} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
105
+ <path fill="currentColor" d="M21 21H3l9-18Z" />
106
+ </svg>
107
+ </div>
108
+ );
109
+ })}
110
+ </div>
111
+ )}
112
+
113
+ <CusNavbar />
114
+ <div className="flex flex-row w-full h-[calc(100vh-4rem)] flex-nowrap items-center justify-between border-t border-primary-950">
115
+ <div className={"border-r border-primary-950 h-full p-5 relative px-0 transition-all " + (sidebar ? "w-[20%] min-w-64" : "w-0 ")}>
116
+ <svg
117
+ onClick={() => {
118
+ setSidebar(!sidebar);
119
+ }}
120
+ className={"absolute top-0 w-10 h-10 p-2 z-50 border border-t-0 border-primary-950 hover:bg-primary-100 cursor-pointer transition-all " + (sidebar ? "border-l-0 right-0 -scale-x-100" : "border-l-0 -right-10")}
121
+ viewBox="-0.2 0 1 1"
122
+ xmlns="http://www.w3.org/2000/svg"
123
+ >
124
+ <path d="m0.138 0.023 0.434 0.417 0.004 0.003c0.015 0.014 0.023 0.033 0.024 0.055l0 0.007c-0.001 0.02 -0.01 0.038 -0.027 0.054l0 0L0.138 0.977a0.082 0.082 0 0 1 -0.114 0 0.079 0.079 0 0 1 0 -0.114l0.376 -0.361L0.024 0.137a0.079 0.079 0 0 1 0 -0.114 0.082 0.082 0 0 1 0.114 0" fill="#1C1C1F" />
125
+ </svg>
126
+ <div className={"flex flex-col w-full h-full gap-3 transition-all origin-left " + (sidebar ? "" : "scale-x-0")}>
127
+ <div className="relative w-[calc(100%-2.5rem)] mx-auto h-10">
128
+ <div className="grid place-items-center absolute text-blue-gray-500 top-2/4 right-12 -translate-y-2/4 w-5 h-5">
129
+ <svg width={16} height={16} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
130
+ <path fill="currentColor" d="M21.71 20.29 18 16.61A9 9 0 1 0 16.61 18l3.68 3.68a1 1 0 0 0 1.42 0 1 1 0 0 0 0-1.39M11 18a7 7 0 1 1 7-7 7 7 0 0 1-7 7" />
131
+ </svg>
132
+ </div>
133
+ <input
134
+ onChange={(event) => {
135
+ setSearch(event.target.value);
136
+ }}
137
+ value={search}
138
+ className="peer w-[calc(100%-2.5rem)] h-full bg-transparent text-blue-gray-700 font-sans font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 border focus:border-2 border-t-transparent focus:border-t-transparent placeholder:opacity-0 focus:placeholder:opacity-100 text-sm px-3 py-2.5 rounded-[7px] !pr-9 border-blue-gray-200 focus:border-gray-900"
139
+ placeholder=" "
140
+ />
141
+ <label className="flex w-[calc(100%-2.5rem)] h-full select-none pointer-events-none absolute left-0 font-normal !overflow-visible truncate peer-placeholder-shown:text-blue-gray-500 leading-tight peer-focus:leading-tight peer-disabled:text-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500 transition-all -top-1.5 peer-placeholder-shown:text-sm text-[11px] peer-focus:text-[11px] before:content[' '] before:block before:box-border before:w-2.5 before:h-1.5 before:mt-[6.5px] before:mr-1 peer-placeholder-shown:before:border-transparent before:rounded-tl-md before:border-t peer-focus:before:border-t-2 before:border-l peer-focus:before:border-l-2 before:pointer-events-none before:transition-all peer-disabled:before:border-transparent after:content[' '] after:block after:flex-grow after:box-border after:w-2.5 after:h-1.5 after:mt-[6.5px] after:ml-1 peer-placeholder-shown:after:border-transparent after:rounded-tr-md after:border-t peer-focus:after:border-t-2 after:border-r peer-focus:after:border-r-2 after:pointer-events-none after:transition-all peer-disabled:after:border-transparent peer-placeholder-shown:leading-[3.75] text-gray-500 peer-focus:text-gray-900 before:border-blue-gray-200 peer-focus:before:!border-gray-900 after:border-blue-gray-200 peer-focus:after:!border-gray-900">Search Roll No. </label>
142
+ </div>
143
+ <div className="w-full h-full flex flex-col gap-2 text-primary-700 overflow-y-scroll pl-6 py-5 px-5 noScrollBars">
144
+ {grns.map((grn, index) => {
145
+ if (search && !grn.supplierName.toLowerCase().includes(search.toLowerCase()) && !grn.buyer.toLowerCase().includes(search.toLowerCase()) && !grn.GRN.toLowerCase().includes(search.toLowerCase())) return null;
146
+ return <GRNCard key={index} GRN={grn} />;
147
+ })}
148
+ </div>
149
+ </div>
150
+ </div>
151
+ <div className={"border-r h-full overflow-y-auto custom-scrollbar " + (sidebar ? "w-[80%]" : "w-full")}>
152
+ <Routes>
153
+ <Route path="/" element={<HomePage />} />
154
+ {/* <Route path="/add-roll" element={<AddRollPage />} /> */}
155
+ <Route path="/roll" element={<RollDetailPage />} />
156
+ <Route path="/grn" element={<GRNDetailPage sidebar={sidebar} />} />
157
+ <Route path="/transcribe" element={<TranscribePage />} />
158
+ <Route path="*" element={<ErrorPage />} />
159
+ </Routes>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ );
164
+ }
165
+
166
+ export default App;
vafront/src/Components/CusNavbar.jsx ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useEffect, useState } from "react";
2
+ import { NavLink } from "react-router-dom";
3
+ import { useAtom } from "jotai";
4
+ import { VoiceAssistAtom } from "../Variables";
5
+
6
+ export function CusNavbar() {
7
+ const [voiceAssist, setVoiceAssist] = useAtom(VoiceAssistAtom);
8
+ const [commands, setCommands] = useState([]);
9
+ const [isListening, setIsListening] = useState(false);
10
+ const [isSpeaking, setIsSpeaking] = useState(false);
11
+ const [infoOpen, setInfoOpen] = useState(false);
12
+ useEffect(() => {
13
+ let tempCommands = [];
14
+ let finalCommands = [];
15
+ let commandsArr = voiceAssist?.getAvailableCommands();
16
+ for (let index = 0; index < commandsArr.length; index++) {
17
+ if (!tempCommands.includes(commandsArr[index]?.indexes?.join(", "))) {
18
+ tempCommands.push(commandsArr[index]?.indexes?.join(", "));
19
+ finalCommands.push(commandsArr[index]);
20
+ }
21
+ }
22
+ setCommands(finalCommands);
23
+ setIsListening(voiceAssist?.isRecognizing());
24
+ setIsSpeaking(voiceAssist?.isSpeaking());
25
+ setInterval(() => {
26
+ setIsListening(voiceAssist?.isRecognizing());
27
+ setIsSpeaking(voiceAssist?.isSpeaking());
28
+ }, 1000);
29
+ }, [voiceAssist, infoOpen]);
30
+ return (
31
+ <div className="h-16 w-full relative z-50">
32
+ <div className="h-full max-w-full rounded-none px-8 pl-4 py-1">
33
+ <div className="flex items-center justify-between text-primary-400">
34
+ <NavLink to="/" className="cursor-pointer w-48 h-full font-medium">
35
+ <svg viewBox="0 0 370.185 62.836" className="h-full w-auto text-primary-900" xmlns="http://www.w3.org/2000/svg">
36
+ <path fill="currentColor" d="M43.192 22.554c.705-4.174 1.102-8.074 1.149-11.46.063-4.577-.488-10.2-3.472-11.004a2.6 2.6 0 0 0-1.094-.06 3 3 0 0 0-.392-.03c-3.562 0-7.798 6.72-11.27 15.022-6.215-5.278-11.757-8.507-15.036-8.507-.917 0-1.66.249-2.206.74-2.7 2.422.358 9.623 5.356 17.185C6.856 26.267-.171 29.222.003 32.77c.238 4.867 13.725 7.11 26.312 7.158a2.66 2.66 0 0 0 2.313 1.356c1.463 0 2.653-1.19 2.653-2.654s-1.19-2.654-2.653-2.654a2.66 2.66 0 0 0-2.543 1.897c-11.14-.084-20.396-1.787-23.68-4.372-.005-.005-.564-.484-.577-1.087-.007-.355.185-.71.571-1.055l.02-.02c2.668-2.056 8.139-3.861 15.025-5.103a106 106 0 0 0 4.724 6.272.48.48 0 0 0 .667.074l.861-.676a.48.48 0 0 0 .077-.677 106 106 0 0 1-4.078-5.37c3.779-.588 7.907-1.01 12.188-1.22q1.623-.08 3.243-.12a125 125 0 0 1 3.92 4.347q-.468 2.013-1.019 4.062a134 134 0 0 1-1.314 4.562q-1.522.122-3.079.205a.48.48 0 0 0-.354.19l-.856 1.127a.479.479 0 0 0 .405.768q1.624-.08 3.22-.199c-4.08 12.503-8.967 20.735-11.797 21.496a1.3 1.3 0 0 1-.305-.152c-.644-.437-.793-1.456-.793-1.465a.476.476 0 0 0-.474-.415h-.002a.48.48 0 0 0-.397.224.48.48 0 0 0-.4-.224.48.48 0 0 0-.474.418c-.256 2.04 1.048 3.035 1.8 3.284a2.6 2.6 0 0 0 1.086.057q.197.03.4.032c4.128 0 9.992-9.78 14.389-23.518 2.554-.254 5.02-.583 7.352-.978 4.765 6.83 7.57 12.689 7 15.234-.114.517-.371.852-.783 1.025a1.5 1.5 0 0 1-.58.107 2.9 2.9 0 0 1-1.08-.24.478.478 0 0 0-.514.797c.652.55 1.35.83 2.074.83a2.8 2.8 0 0 0 1.66-.55c2.665-2.391-.253-9.567-5.636-17.596 2.474-.482 4.773-1.041 6.83-1.673 4.375-1.343 9.558-3.593 9.407-6.68-.21-4.265-10.588-6.515-21.62-7.04M40.678 2.803l.012.024c1.34 3.728 1.161 11.038-.334 19.63a106 106 0 0 0-2.264-.024c-.696 0-1.404.014-2.11.026a114 114 0 0 0-5.643-5.485c3.011-7.443 6.363-12.983 9.096-14.821.004-.003.196-.12.467-.197.318.118.575.397.776.847M29.549 18.994a113 113 0 0 1 3.664 3.545c-.41.016-.817.025-1.227.045-1.269.062-2.542.148-3.807.25q.665-1.982 1.37-3.84m8.76 5.484q.844.001 1.673.013-.183.939-.384 1.893-.324-.368-.652-.734a128 128 0 0 0-1.06-1.166c.14 0 .283-.006.423-.006m2.44 9.177q.283-1.055.545-2.105a118 118 0 0 1 3.838 4.968c-1.732.268-3.539.501-5.399.695q.526-1.743 1.016-3.558M13.503 8.226c3.355.791 8.359 4.026 13.81 8.764a108 108 0 0 0-2.19 6.13 110 110 0 0 0-6.687.918c-4.09-6.065-6.57-11.374-6.618-14.455.005-.233.086-1.391 1.28-1.391q.178 0 .38.032zm48.442 23.186-.06.034c-2.873 1.9-8.099 3.55-14.545 4.704a112 112 0 0 0-5.446-7.088 118 118 0 0 0 .941-4.499c10.3.39 18.246 2.105 19.994 4.434.3.4.386.796.265 1.21-.216.749-1.141 1.201-1.149 1.205" />
37
+ <path fill="currentColor" d="M112.545 13.17h5.581l-13.82 37.597h-5.535L85.001 13.17h5.553l11.01 31.109zm22.919 38.103c-7.683 0-13.477-5.238-13.477-13.695 0-8.426 5.74-13.667 13.477-13.667s13.455 5.24 13.455 13.667c0 8.457-5.745 13.695-13.455 13.695m-.054-4.201c4.813 0 8.456-3.725 8.456-9.494 0-5.745-3.643-9.464-8.454-9.464-4.759 0-8.35 3.722-8.35 9.464 0 5.772 3.591 9.494 8.35 9.494m23.08-28.451c-1.808 0-3.349-1.49-3.349-3.322s1.541-3.3 3.349-3.3c1.783 0 3.297 1.465 3.297 3.297s-1.514 3.325-3.294 3.325m-2.611 32.146V24.444h5.132v26.323zm25.366.479c-7.658 0-13.321-5.45-13.321-13.668s5.663-13.667 13.321-13.667c5.955 0 10.635 3.245 12.203 8.88l-4.759.72c-1.17-3.51-4.013-5.397-7.498-5.397-4.68 0-8.162 3.722-8.162 9.464 0 5.718 3.485 9.467 8.162 9.467 3.485 0 6.327-1.887 7.498-5.396l4.76.716c-1.569 5.608-6.328 8.88-12.204 8.88m42.117-14.144-.082 1.356h-20.392c.185 5.82 3.855 8.638 8.217 8.638 3.136 0 5.742-1.701 7.07-4.546l4.629.904c-1.863 4.892-6.303 7.819-11.648 7.819-7.814 0-13.267-5.053-13.267-13.668s5.584-13.694 13.11-13.694c7.152 0 12.336 4.31 12.36 13.19zm-12.34-9.306c-4.067 0-7.124 2.178-7.922 6.78h15.13c-.428-4.575-3.325-6.78-7.207-6.78m44.775 22.97-3.137-8.774h-16.804l-3.136 8.775h-5.506l13.853-37.597h6.382l13.853 37.597zm-18.291-13.4h13.504l-6.752-18.958zm38.313 13.907c-5.636 0-9.864-2.5-10.69-7.313l4.387-1.25c.64 3.137 3.033 4.787 6.276 4.787 2.447 0 5.077-.931 4.998-3.828-.081-3.112-3.643-3.619-7.868-4.92-3.591-1.09-7.074-2.578-7.074-7.259 0-5.21 4.28-7.525 9.464-7.525 4.841 0 8.909 2.047 9.758 6.888l-4.12 1.008c-.639-3.003-2.978-4.253-5.608-4.253-2.341 0-4.762.958-4.762 3.512 0 2.764 3.112 3.403 6.488 4.28 4.122 1.035 8.67 2.5 8.67 8.056 0 5.663-4.708 7.814-9.92 7.814zm25.34 0c-5.637 0-9.865-2.5-10.69-7.313l4.386-1.25c.637 3.137 3.03 4.787 6.276 4.787 2.445 0 5.078-.931 4.999-3.828-.082-3.112-3.643-3.619-7.869-4.92-3.593-1.09-7.076-2.578-7.076-7.259 0-5.21 4.283-7.525 9.467-7.525 4.838 0 8.908 2.047 9.758 6.888l-4.122 1.008c-.637-3.003-2.976-4.253-5.609-4.253-2.341 0-4.76.958-4.76 3.512 0 2.764 3.11 3.403 6.489 4.28 4.12 1.035 8.666 2.5 8.666 8.056 0 5.663-4.705 7.814-9.916 7.814zm19.46-32.652c-1.807 0-3.348-1.49-3.348-3.322s1.54-3.3 3.349-3.3c1.78 0 3.297 1.465 3.297 3.297s-1.517 3.325-3.295 3.325m-2.608 32.146V24.444h5.132v26.323zm22.761.506c-5.636 0-9.867-2.5-10.689-7.313l4.384-1.25c.64 3.137 3.033 4.787 6.278 4.787 2.445 0 5.078-.931 4.999-3.828-.082-3.112-3.643-3.619-7.871-4.92-3.591-1.09-7.074-2.578-7.074-7.259 0-5.21 4.28-7.525 9.467-7.525 4.838 0 8.906 2.047 9.758 6.888l-4.122 1.008c-.637-3.003-2.979-4.253-5.609-4.253-2.341 0-4.76.958-4.76 3.512 0 2.764 3.11 3.403 6.486 4.28 4.122 1.035 8.67 2.5 8.67 8.056 0 5.663-4.708 7.814-9.92 7.814zm25.498-.506c-4.44 0-7.18-2.66-7.18-7.338V28.46h-5.372v-4.016h1.942c2.739 0 3.855-1.143 3.855-4.2v-4.545h4.707v8.748h5.955v4.016h-5.955v14.435c0 2.527 1.462 3.855 3.534 3.855h2.423v4.014z" />
38
+ </svg>
39
+ </NavLink>
40
+ <div className="flex items-center gap-4">
41
+ <div className="mr-4">
42
+ <div className="mt-2 mb-4 flex flex-row items-center gap-3">
43
+ <NavLink to="/" className={({ isActive }) => (isActive ? "text-white bg-gradient-to-tr from-primary-900 to-primary-700 p-2 px-4 rounded-lg" : "text-primary-900 p-2 px-4")}>
44
+ Home
45
+ </NavLink>
46
+ {/* <NavLink to="/add-roll" className={({ isActive }) => (isActive ? "text-white bg-gradient-to-tr from-primary-900 to-primary-700 p-2 px-4 rounded-lg" : "text-primary-900 p-2 px-4")}>
47
+ Add Roll
48
+ </NavLink> */}
49
+ <NavLink to="/grn" className={({ isActive }) => (isActive ? "text-white bg-gradient-to-tr from-primary-900 to-primary-700 p-2 px-4 rounded-lg" : "text-primary-900 p-2 px-4")}>
50
+ GRN Detail
51
+ </NavLink>
52
+ <NavLink to="/roll" className={({ isActive }) => (isActive ? "text-white bg-gradient-to-tr from-primary-900 to-primary-700 p-2 px-4 rounded-lg" : "text-primary-900 p-2 px-4")}>
53
+ Roll Detail
54
+ </NavLink>
55
+ {/* <NavLink to="/Docs" className={({ isActive }) => (isActive ? "text-white bg-gradient-to-tr from-primary-900 to-primary-700 p-2 px-4 rounded-lg" : "text-primary-900 p-2 px-4")}>
56
+ Docs
57
+ </NavLink> */}
58
+ <NavLink to="/transcribe" className={({ isActive }) => (isActive ? "text-white bg-gradient-to-tr from-primary-900 to-primary-700 p-2 px-4 rounded-lg" : "text-primary-900 p-2 px-4")}>
59
+ Transcribe
60
+ </NavLink>
61
+ {isSpeaking ? (
62
+ <svg className={"h-7 w-7 animate-pulse text-green-500 "} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.459 87.459" xmlSpace="preserve">
63
+ <path fill="currentColor" d="M37.44 73.283H7.694V55.66A23.82 23.82 0 0 1 0 38.09c0-13.186 10.728-23.913 23.913-23.913 10.765 0 20.254 7.251 23.074 17.634l.088.32.178 3.921 7.217 10.12-6.344 4.608v3.524c0 4.244-3.453 7.698-7.7 7.698h-2.985zm-23.746-6H31.44V56.004h8.985c.938 0 1.7-.763 1.7-1.699v-6.58l4.006-2.91-4.794-6.72-.227-5.016c-2.214-7.612-9.241-12.9-17.198-12.9-9.877 0-17.913 8.036-17.913 17.913 0 5.4 2.402 10.458 6.591 13.877l1.103.9zm47.458-10.311L56.91 52.73c2.706-2.707 2.706-7.111-.001-9.819l4.244-4.242c5.045 5.046 5.045 13.258-.001 18.303" />
64
+ <path fill="currentColor" d="m69.251 63.361-4.242-4.242c6.229-6.229 6.229-16.366 0-22.596l4.242-4.242c8.567 8.569 8.567 22.512 0 31.08" />
65
+ <path fill="currentColor" d="m78.555 69.351-4.244-4.242c9.531-9.533 9.531-25.043.002-34.575l4.242-4.242c11.872 11.869 11.872 31.186 0 43.059" />
66
+ </svg>
67
+ ) : (
68
+ <svg title={"Voice Recognition " + (isListening ? "Working" : "Stopped")} className={"h-7 w-7 animate-pulse " + (isListening ? "text-green-500 " : "text-red-500")} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
69
+ <path fill="currentColor" d="M0 12C0 5.373 5.373 0 12 0s12 5.373 12 12-5.373 12-12 12C5.376 23.992.008 18.624 0 12.001zm2.4 0c0 5.302 4.298 9.6 9.6 9.6s9.6-4.298 9.6-9.6-4.298-9.6-9.6-9.6c-5.299.006-9.594 4.301-9.6 9.599zm4 0a5.6 5.6 0 1 1 11.2 0 5.6 5.6 0 0 1-11.2 0" />
70
+ </svg>
71
+ )}
72
+ <svg
73
+ onClick={() => {
74
+ setInfoOpen(!infoOpen);
75
+ }}
76
+ className="h-7 w-auto border-2 border-primary-700 text-primary-700 hover:scale-110 transition-all cursor-pointer rounded-full p-1"
77
+ viewBox="-6.5 0 24 24"
78
+ xmlns="http://www.w3.org/2000/svg"
79
+ >
80
+ <path fill="currentColor" d="M8.436.006a2.24 2.24 0 0 1 2.408 2.354v-.006a3.156 3.156 0 0 1-3.151 3.01l-.065-.001h.003a2.15 2.15 0 0 1-2.367-2.398l-.001.01A3.087 3.087 0 0 1 8.44.004h-.005zM3.489 24c-1.268 0-2.199-.783-1.311-4.226l1.456-6.108c.254-.978.295-1.369 0-1.369a9.6 9.6 0 0 0-3.035 1.359l.033-.021-.633-1.057c3.086-2.622 6.638-4.159 8.158-4.159 1.268 0 1.48 1.526.845 3.874l-1.666 6.421c-.296 1.135-.168 1.526.126 1.526a6.55 6.55 0 0 0 2.863-1.456l-.008.007.72.979c-3.004 3.052-6.281 4.232-7.549 4.232z" />
81
+ </svg>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ </div>
87
+ <div
88
+ onMouseLeave={() => {
89
+ setInfoOpen(false);
90
+ }}
91
+ className={"absolute top-100 right-10 overflow-y-auto overflow-x-clip custom-scrollbar bg-white border border-t-0 border-primary-950 rounded-b-xl w-fit h-fit max-h-96 shadow-lg origin-top transition-all " + (infoOpen ? "scale-y-100" : "scale-y-0")}
92
+ >
93
+ {commands?.map((command, index) => {
94
+ return (
95
+ <p key={index} className="p-1 pr-4 pl-2 hover:text-primary-950 cursor-pointer hover:scale-105 origin-left text-primary-900 font-semibold whitespace-nowrap">
96
+ {">> "}
97
+ {command?.indexes?.join(", ")}
98
+ </p>
99
+ );
100
+ })}
101
+ </div>
102
+ </div>
103
+ );
104
+ }
vafront/src/Components/GRNCard.jsx ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react";
2
+ import { useAtom } from "jotai";
3
+ import { CurrentGRNAtom } from "../Variables";
4
+ import { useNavigate } from "react-router-dom";
5
+
6
+ function GRNCard({ GRN }) {
7
+ const [currentGRN, setCurrentGRN] = useAtom(CurrentGRNAtom);
8
+ const navigate = useNavigate();
9
+ return (
10
+ <div
11
+ onClick={() => {
12
+ setCurrentGRN(GRN);
13
+ localStorage.setItem("currentGRN", JSON.stringify(GRN));
14
+ navigate("/grn");
15
+ }}
16
+ className="relative overflow-hidden hover:translate-x-3 cursor-pointer hover:brightness-105 transition-all rounded-xl bg-gray-100 shadow-inner text-primary-700 border border-primary-950/50 mx-0 flex items-center "
17
+ >
18
+ <div className="flex w-full flex-col gap-0.5 py-2 px-3">
19
+ <div className="flex flex-wrap gap-x-3 items-center justify-between">
20
+ <h5 className="text-sm font-semibold whitespace-nowrap text-primary-950">GRN : {GRN?.GRN}</h5>
21
+ <h5 className="text-sm font-semibold whitespace-nowrap text-primary-950">Quant : {GRN?.quantity}</h5>
22
+ </div>
23
+ <p className="text-sm text-primary-900 truncate" title={GRN?.supplierName}>
24
+ Supplier Name : {GRN?.supplierName}
25
+ </p>
26
+ <p className="text-sm text-primary-900 truncate" title={GRN?.buyer}>
27
+ Buyer : {GRN?.buyer}
28
+ </p>
29
+ </div>
30
+ </div>
31
+ );
32
+ }
33
+
34
+ export default GRNCard;
vafront/src/Components/RollCard.jsx ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react";
2
+ import { useAtom } from "jotai";
3
+ import { CurrentRollAtom } from "../Variables";
4
+ import { useNavigate } from "react-router-dom";
5
+
6
+ function RollCard({ roll, index }) {
7
+ const [currentRoll, setCurrentRoll] = useAtom(CurrentRollAtom);
8
+ const navigate = useNavigate();
9
+ return (
10
+ <div
11
+ key={index}
12
+ onClick={() => {
13
+ setCurrentRoll(roll);
14
+ navigate("/roll");
15
+ }}
16
+ className="relative hover:scale-90 cursor-pointer hover:brightness-105 transition-all rounded-xl bg-gray-100 shadow-inner text-primary-700 border border-primary-950/50 mx-0 flex items-center "
17
+ >
18
+ <div className="flex w-full flex-col gap-0.5 py-2 px-3">
19
+ <div className="flex flex-wrap items-center justify-between">
20
+ <h5 className="text-sm font-semibold whitespace-nowrap text-primary-950">RollNo : {roll?.name}</h5>
21
+ </div>
22
+ <p className="text-sm text-primary-900 truncate">minWidth : {roll?.minWidth}</p>
23
+ <p className="text-sm text-primary-900 truncate">rLength : {roll?.rLength}</p>
24
+ </div>
25
+ </div>
26
+ );
27
+ }
28
+
29
+ export default RollCard;
vafront/src/Pages/AddRollPage.jsx ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from "react";
2
+ import { VoiceAssistAtom, rollsAtom } from "../Variables";
3
+ import { useAtom } from "jotai";
4
+
5
+ function AddRollPage() {
6
+ const [name, setName] = useState("");
7
+ const [client, setClient] = useState("");
8
+ const [stock, setStock] = useState("");
9
+ const [description, setDescription] = useState("");
10
+ const [image, setImage] = useState(null);
11
+ const [success, setSuccess] = useState(null);
12
+ const [error, setError] = useState(null);
13
+ const [voiceAssist, setVoiceAssist] = useAtom(VoiceAssistAtom);
14
+ const [rolls, setRolls] = useAtom(rollsAtom);
15
+ useEffect(() => {
16
+ voiceAssist.on(["roll number *", "role number * ", "roll no. *", "role no. *"], true).then((i, wildcard) => {
17
+ setName(parseInt(wildcard));
18
+ });
19
+ voiceAssist.on(["client *"], true).then((i, wildcard) => {
20
+ setClient(wildcard);
21
+ });
22
+ voiceAssist.on(["stock *"], true).then((i, wildcard) => {
23
+ setStock(parseInt(wildcard));
24
+ });
25
+ voiceAssist.on(["description *"], true).then((i, wildcard) => {
26
+ setDescription(wildcard);
27
+ });
28
+ voiceAssist.on(["submit"]).then((i) => {
29
+ submitBtn.click();
30
+ });
31
+ }, []);
32
+ return (
33
+ <div className="flex flex-col lg:flex-row gap-10 items-center justify-center w-full h-full">
34
+ <div className="max-w-80 w-[80%] mx-auto lg:mx-0 lg:w-auto">
35
+ <h4 className="font-semibold text-primary-900">Upload Image</h4>
36
+ <div className="relative overflow-hidden bg-primary-200 hover:bg-primary-300/75 group/upload cursor-pointer border-2 border-dashed transition-all border-primary-900 rounded-lg w-full lg:w-64 h-16 lg:h-64 relativ flex flex-col items-center justify-center">
37
+ <input
38
+ onChange={(event) => {
39
+ let dataUri = URL.createObjectURL(event.target.files[0]);
40
+ setImage(dataUri);
41
+ }}
42
+ id="sampleImage"
43
+ type="file"
44
+ allow=".png,.jpg,.jpeg"
45
+ className="w-full h-full absolute top-0 left-0 opacity-0"
46
+ />
47
+ {image === null ? (
48
+ <div>
49
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" className="w-32 h-32 text-primary-800 transition-all group-hover/upload:text-primary-700 " xmlSpace="preserve">
50
+ <path d="M22.414 23.586a2 2 0 1 1-2.828 2.828L18 24.828V29a2 2 0 0 1-4 0v-4.172l-1.586 1.586a2 2 0 1 1-2.828-2.828l5-5a2 2 0 0 1 2.828 0zM26 10A9 9 0 0 0 8.2 8.12 6 6 0 1 0 7 20h4.758l2.121-2.121A2.98 2.98 0 0 1 16 17c.802 0 1.555.312 2.121.879L20.242 20H26a5 5 0 0 0 0-10" fill="currentColor" />
51
+ </svg>
52
+ <h6 className=" font-semibold text-primary-900 group-hover/upload:text-primary-800 transition-all -mb-3">Upload Image</h6>
53
+ </div>
54
+ ) : (
55
+ <img src={image} className="w-full h-full object-cover"></img>
56
+ )}
57
+ </div>
58
+ </div>
59
+ <div className="relative flex flex-col bg-clip-border rounded-xl bg-transparent text-primary-700 shadow-none">
60
+ <h4 className="text-xl font-semibold text-primary-900 lg:w-full w-[80%] lg:mx-0 mx-auto">Add New Roll</h4>
61
+ <p className="text-primary-700 mt-1 font-normal lg:w-full w-[80%] lg:mx-0 mx-auto">Please fill in the form to register a new roll.</p>
62
+ {success && (
63
+ <div role="alert" className="relative w-full text-base font-regular px-4 py-4 mt-3 rounded-none border-l-4 border-green-600 bg-green-600/10 font-medium text-green-600 flex" style={{ opacity: 1 }}>
64
+ <div className="shrink-0">
65
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="h-6 w-6">
66
+ <path fillRule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm13.36-1.814a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z" clipRule="evenodd" />
67
+ </svg>
68
+ </div>
69
+ <div className="ml-3 mr-12 truncate" id="successMsg">
70
+ {success}
71
+ </div>
72
+ </div>
73
+ )}
74
+ {error && (
75
+ <div role="alert" className="relative w-full text-base font-regular px-4 py-4 mt-3 rounded-none border-l-4 border-red-500 bg-red-500/10 font-medium text-red-500 flex" style={{ opacity: 1 }}>
76
+ <div className="shrink-0">
77
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="h-6 w-6">
78
+ <path fillRule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm13.36-1.814a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z" clipRule="evenodd" />
79
+ </svg>
80
+ </div>
81
+ <div className="ml-3 mr-12 truncate" id="errorMsg">
82
+ {error}
83
+ </div>
84
+ </div>
85
+ )}
86
+
87
+ <div className="mt-8 mb-2 max-w-80 lg:w-full w-[80%] lg:mx-0 mx-auto">
88
+ <div className="mb-1 flex flex-col gap-3">
89
+ <h6 className=" font-semibold text-primary-900">Roll No.</h6>
90
+ <input
91
+ onChange={(event) => {
92
+ setName(event.target.value);
93
+ }}
94
+ value={name}
95
+ placeholder={123}
96
+ type="number"
97
+ className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900"
98
+ />
99
+ <h6 className=" font-semibold text-primary-900">Client</h6>
100
+ <input
101
+ onChange={(event) => {
102
+ setClient(event.target.value);
103
+ }}
104
+ value={client}
105
+ placeholder="Sahi"
106
+ className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900"
107
+ />
108
+ <h6 className=" font-semibold text-primary-900">Stock</h6>
109
+ <input
110
+ onChange={(event) => {
111
+ setStock(event.target.value);
112
+ }}
113
+ value={stock}
114
+ placeholder={10}
115
+ type="number"
116
+ className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900"
117
+ />
118
+ <h6 className=" font-semibold text-primary-900">Description</h6>
119
+ <input
120
+ onChange={(event) => {
121
+ setDescription(event.target.value);
122
+ }}
123
+ value={description}
124
+ placeholder="Plain white Fabric"
125
+ className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900"
126
+ />
127
+ </div>
128
+ <button
129
+ id="submitBtn"
130
+ onClick={() => {
131
+ console.log(name, client, stock);
132
+ if (!name || !client || !stock || !description || !image) {
133
+ setError("Please fill all the fields");
134
+ setTimeout(() => {
135
+ setError(null);
136
+ }, 3000);
137
+ return;
138
+ }
139
+ let sampleImage = document.getElementById("sampleImage");
140
+ let imageFile = sampleImage.files[0];
141
+ let data = new FormData();
142
+ data.append("name", name);
143
+ data.append("client", client);
144
+ data.append("stock", stock);
145
+ data.append("description", description);
146
+ data.append("image", imageFile);
147
+ fetch("/api/rollEntry", {
148
+ method: "POST",
149
+ body: data,
150
+ })
151
+ .then((response) => response.json())
152
+ .then((data) => {
153
+ if (data.status === "success") {
154
+ setClient("");
155
+ setName("");
156
+ setStock("");
157
+ setDescription("");
158
+ setImage(null);
159
+ setSuccess(data.msg);
160
+ setTimeout(() => {
161
+ setSuccess(null);
162
+ }, 3000);
163
+ fetch("/api/rolls")
164
+ .then((res) => res.json())
165
+ .then((data) => {
166
+ setRolls(data["data"]);
167
+ })
168
+ .catch((err) => console.error(err));
169
+ } else {
170
+ setError(data.msg);
171
+ setTimeout(() => {
172
+ setError(null);
173
+ }, 3000);
174
+ voiceAssist.say(data.msg);
175
+ }
176
+ })
177
+ .catch((error) => console.error("Error:", error));
178
+ }}
179
+ className="align-middle select-none font-sans font-bold text-center uppercase transition-all disabled:opacity-50 disabled:shadow-none disabled:pointer-events-none text-xs py-3 px-6 rounded-lg bg-gradient-to-tr from-primary-950 to-primary-800 text-white shadow-md shadow-gray-900/10 hover:shadow-lg hover:shadow-gray-900/20 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none block w-full mt-6"
180
+ type="button"
181
+ >
182
+ Submit
183
+ </button>
184
+ </div>
185
+ </div>
186
+ </div>
187
+ );
188
+ }
189
+
190
+ export default AddRollPage;
vafront/src/Pages/ErrorPage.jsx ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import React from "react";
2
+
3
+ function ErrorPage() {
4
+ return <div>ErrorPage</div>;
5
+ }
6
+
7
+ export default ErrorPage;
vafront/src/Pages/GRNDetailPage.jsx ADDED
@@ -0,0 +1,315 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from "react";
2
+ import { useAtom } from "jotai";
3
+ import { CurrentGRNAtom, VoiceAssistAtom, grnsAtom, CurrentRollAtom, TranscribeAtom } from "../Variables";
4
+ import { useNavigate } from "react-router";
5
+ import RollCard from "../Components/RollCard";
6
+
7
+ const GRNDetailPage = ({ sidebar }) => {
8
+ const [currentGRN, setCurrentGRN] = useAtom(CurrentGRNAtom);
9
+ const [voiceAssist, setVoiceAssist] = useAtom(VoiceAssistAtom);
10
+ const [currentRoll, setCurrentRoll] = useAtom(CurrentRollAtom);
11
+ const [transcribe, setTranscribe] = useAtom(TranscribeAtom);
12
+ const [currentGRNRolls, setCurrentGRNRolls] = useState([]);
13
+ const [fabricForm, setFabricForm] = useState("");
14
+ const [POWidth, setPOWidth] = useState(0);
15
+ const [PointsUOM, setPointsUOM] = useState("");
16
+ const [Tolarence, setTolarence] = useState(0);
17
+ const navigate = useNavigate();
18
+ useEffect(() => {
19
+ fetch("/api/grnRolls/" + currentGRN?.GRN)
20
+ .then((res) => res.json())
21
+ .then((data) => {
22
+ setCurrentGRNRolls(data["data"]);
23
+ voiceAssist.on(["roll *", "open roll *"], true).then((i, wildcard) => {
24
+ wildcard = wildcard.replace(/ /g, "");
25
+ let found = false;
26
+ for (let index = 0; index < data["data"].length; index++) {
27
+ if (data["data"][index].name.toLowerCase() == wildcard.toLowerCase()) {
28
+ setCurrentRoll(data["data"][index]);
29
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "open roll " + wildcard, isCommand: true }]);
30
+ navigate("/roll");
31
+ found = true;
32
+ }
33
+ }
34
+ if (!found) {
35
+ voiceAssist.say("No roll found with that Number");
36
+ }
37
+ });
38
+ })
39
+ .catch((err) => {
40
+ window.location.href = "/";
41
+ });
42
+ }, [currentGRN]);
43
+ useEffect(() => {
44
+ setFabricForm(currentGRN?.fabricForm);
45
+ setPOWidth(currentGRN?.POWidth);
46
+ setPointsUOM(currentGRN?.PointsUOM);
47
+ setTolarence(currentGRN?.Tolarence);
48
+ voiceAssist.emptyCommands();
49
+ voiceAssist.on(["open *", "grn *", "open grn *"], true).then((i, wildcard) => {
50
+ wildcard = wildcard.replace(/\s/g, "");
51
+ let found = false;
52
+ for (let index = 0; index < grns.length; index++) {
53
+ if (grns[index].GRN.toLowerCase() == wildcard.toLowerCase()) {
54
+ setCurrentGRN(grns[index]);
55
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "open GRN " + wildcard, isCommand: true }]);
56
+ navigate("/grn");
57
+ localStorage.setItem("currentGRN", JSON.stringify(grns[index]));
58
+ found = true;
59
+ }
60
+ }
61
+ if (!found) {
62
+ voiceAssist.say("No GRN found with that Number");
63
+ }
64
+ });
65
+ voiceAssist.on(["search *"], true).then((i, wildcard) => {
66
+ wildcard = wildcard.replace(/ /g, "");
67
+ setSearch(wildcard);
68
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "search " + wildcard, isCommand: true }]);
69
+ });
70
+ voiceAssist.on(["transcribe"]).then((i) => {
71
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "transcribe", isCommand: true }]);
72
+ navigate("/transcribe");
73
+ });
74
+ voiceAssist.on(["home", "go to home"]).then((i) => {
75
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "home", isCommand: true }]);
76
+ navigate("/");
77
+ });
78
+ voiceAssist.on(["refresh"]).then((i) => {
79
+ window.location.reload();
80
+ });
81
+ voiceAssist.on(["c1 *", "C 1 *", "c 1 *", "C1 *", "c1*", "C 1*", "c 1*", "C1*"], true).then((i, wildcard) => {
82
+ let finalWildcard = "";
83
+ if (wildcard == 1) {
84
+ finalWildcard = "Roll";
85
+ } else {
86
+ finalWildcard = "Than";
87
+ }
88
+ setFabricForm(finalWildcard);
89
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Fabric Form Updated to " + finalWildcard, isCommand: true }]);
90
+ });
91
+ voiceAssist.on(["c2 *", "C 2 *", "c 2 *", "C2 *", "c2*", "C 2*", "c 2*", "C2*"], true).then((i, wildcard) => {
92
+ setPOWidth(wildcard);
93
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "PO Width Updated to " + wildcard, isCommand: true }]);
94
+ });
95
+ voiceAssist.on(["c3 *", "C 3 *", "c 3 *", "C3 *", "c3*", "C 3*", "c 3*", "C3*"], true).then((i, wildcard) => {
96
+ let finalWildcard = "";
97
+ if (wildcard == 1) {
98
+ finalWildcard = "YRD";
99
+ } else {
100
+ finalWildcard = "MTR";
101
+ }
102
+ setPointsUOM(finalWildcard);
103
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Points UOM Updated to " + finalWildcard, isCommand: true }]);
104
+ });
105
+ voiceAssist.on(["c4 *", "C 4 *", "c 4 *", "C4 *", "c4*", "C 4*", "c 4*", "C4*"], true).then((i, wildcard) => {
106
+ let finalWildcard = "";
107
+ if (wildcard == 1) {
108
+ finalWildcard = 20;
109
+ } else {
110
+ finalWildcard = 30;
111
+ }
112
+ setTolarence(finalWildcard);
113
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Tolarence Updated to " + finalWildcard, isCommand: true }]);
114
+ });
115
+ voiceAssist.on(["submit GRN", "update GRN", "submit grn", "update grn"]).then((i) => {
116
+ let formData = new FormData();
117
+ formData.append("fabricForm", fabricForm);
118
+ formData.append("POWidth", POWidth);
119
+ formData.append("PointsUOM", PointsUOM);
120
+ formData.append("Tolarence", Tolarence);
121
+ console.log(currentGRN);
122
+ fetch("/api/GRNUpdate/" + currentGRN?.GRN, {
123
+ method: "POST",
124
+ body: formData,
125
+ })
126
+ .then((res) => res.json())
127
+ .then((data) => {
128
+ if (data["status"] == "success") {
129
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: data["msg"], isCommand: true }]);
130
+ voiceAssist.say(data["msg"]);
131
+ } else {
132
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: data["msg"], isCommand: false }]);
133
+ voiceAssist.say("GRN Update Failed");
134
+ }
135
+ })
136
+ .catch((err) => console.error(err));
137
+ });
138
+ }, [voiceAssist]);
139
+
140
+ if (currentGRN?.GRN !== "") {
141
+ return (
142
+ <div className="p-10">
143
+ <div className="flex flex-nowrap items-center justify-between">
144
+ <h1 className="text-2xl font-semibold text-primary-900">GRN : {currentGRN?.GRN}</h1>
145
+ <h1 className="text-lg text-primary-900">* Only Fields with Command Code are editable</h1>
146
+ </div>
147
+ <div className={"w-full mt-3 grid-cols-1 md:grid-cols-4 grid overflow-hidden border-2 border-b-0 border-primary-950 rounded-lg " + (sidebar ? "text-xs" : "text-sm")}>
148
+ <div className="flex item-center justify-between border-b-2 border-primary-950">
149
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">GRN#</p>
150
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.GRN}</p>
151
+ </div>
152
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
153
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Supplier#</p>
154
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.supplier}</p>
155
+ </div>
156
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
157
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Buyer</p>
158
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.buyer}</p>
159
+ </div>
160
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
161
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Item#</p>
162
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.item}</p>
163
+ </div>
164
+ <div className="flex item-center justify-between border-b-2 border-primary-950">
165
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Supplier Name</p>
166
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.supplierName}</p>
167
+ </div>
168
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
169
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">PCH</p>
170
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.PCH}</p>
171
+ </div>
172
+ <div className="flex col-span-2 item-center justify-between border-b-2 border-primary-950 md:border-l-2">
173
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Fabric Description</p>
174
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.fabricDescription}</p>
175
+ </div>
176
+ <div className="flex item-center justify-between border-b-2 border-primary-950">
177
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Quantity</p>
178
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.quantity}</p>
179
+ </div>
180
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
181
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Color</p>
182
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.color}</p>
183
+ </div>
184
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
185
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Invoice#</p>
186
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.invoice}</p>
187
+ </div>
188
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
189
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 whitespace-nowrap">
190
+ PO Width <span className="bg-primary-800 font-normal text-white p-1 rounded ml-2">(C2)</span>
191
+ </p>
192
+ <input
193
+ className="px-3 py-1 truncate3 focus:bg-primary-100 focus:outline-none"
194
+ value={POWidth}
195
+ onChange={(event) => {
196
+ setPOWidth(event.target.value);
197
+ }}
198
+ />
199
+ </div>
200
+ <div className="flex item-center justify-between border-b-2 border-primary-950">
201
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Fabric Odour</p>
202
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.fabricOdour}</p>
203
+ </div>
204
+
205
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
206
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 whitespace-nowrap">
207
+ Fabric Form <span className="bg-primary-800 font-normal text-white p-1 rounded">(C11/C12)</span>
208
+ </p>
209
+ <select
210
+ onChange={(event) => {
211
+ setFabricForm(event.target.value);
212
+ }}
213
+ value={fabricForm}
214
+ className="px-3 py-1 truncate3 focus:bg-primary-100 focus:outline-none"
215
+ >
216
+ <option value="Roll">Roll</option>
217
+ <option value="Than">Than</option>
218
+ </select>
219
+ </div>
220
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
221
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">PO#</p>
222
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.PO}</p>
223
+ </div>
224
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
225
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Item Description</p>
226
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.itemDescription}</p>
227
+ </div>
228
+ <div className="flex item-center justify-between border-b-2 border-primary-950">
229
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 whitespace-nowrap">
230
+ Points UOM <span className="bg-primary-800 font-normal text-white p-1 rounded">(C31/C32)</span>
231
+ </p>
232
+ <select
233
+ onChange={(event) => {
234
+ setPointsUOM(event.target.value);
235
+ }}
236
+ value={PointsUOM}
237
+ className="px-3 py-1 truncate3 focus:bg-primary-100 focus:outline-none"
238
+ >
239
+ <option value="YRD">YRD</option>
240
+ <option value="MTR">MTR</option>
241
+ </select>
242
+ </div>
243
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
244
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Basic UOM</p>
245
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.basicUOM}</p>
246
+ </div>
247
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
248
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Warehouse</p>
249
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.Warehouse}</p>
250
+ </div>
251
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
252
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 whitespace-nowrap">
253
+ Tolarence <span className="bg-primary-800 font-normal text-white p-1 rounded">(C41/C42)</span>
254
+ </p>
255
+ <select
256
+ onChange={(event) => {
257
+ setTolarence(event.target.value);
258
+ }}
259
+ value={Tolarence}
260
+ className="px-3 py-1 truncate3 focus:bg-primary-100 focus:outline-none"
261
+ >
262
+ <option value={20}>20</option>
263
+ <option value={30}>30</option>
264
+ </select>
265
+ </div>
266
+ <div className="flex item-center justify-between border-b-2 border-primary-950">
267
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">PO UOM</p>
268
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.POUOM}</p>
269
+ </div>
270
+
271
+ <div className="flex item-center justify-between border-b-2 border-primary-950 md:border-l-2">
272
+ <p className="bg-gradient-to-r from-primary-200 via-primary-200 to-white font-semibold px-3 py-1 ">Conv Factor</p>
273
+ <p className="px-3 py-1 truncate3 bg-white">{currentGRN?.convFactor}</p>
274
+ </div>
275
+ <div className="flex col-span-2 item-center justify-between border-b-2 border-primary-950 md:border-l-2"></div>
276
+ </div>
277
+
278
+ <div className="grid grid-cols-2 md:grid-cols-4 mt-5 gap-3">
279
+ {currentGRNRolls.map((roll, index) => {
280
+ return <RollCard key={index} roll={roll} />;
281
+ })}
282
+ </div>
283
+ </div>
284
+ );
285
+ } else {
286
+ useEffect(() => {
287
+ voiceAssist.say("No GRN selected, redirecting to home page", {
288
+ onEnd: () => {
289
+ navigate("/");
290
+ },
291
+ });
292
+ }, []);
293
+ return (
294
+ <div className="w-full h-full flex items-center justify-center">
295
+ <div className="flex flex-col items-center justify-center gap-5">
296
+ <svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 647.636 632.174" className="w-[50%] h-[50%] opacity-80">
297
+ <path d="M411.146 142.174h-174.51a15.02 15.02 0 0 0-15 15v387.85l-2 .61-42.81 13.11a8.007 8.007 0 0 1-9.99-5.31l-127.34-415.95a8.003 8.003 0 0 1 5.31-9.99l65.97-20.2 191.25-58.54 65.97-20.2a7.99 7.99 0 0 1 9.99 5.3l32.55 106.32Z" fill="#f2f2f2" />
298
+ <path d="m449.226 140.174-39.23-128.14a16.994 16.994 0 0 0-21.23-11.28l-92.75 28.39-191.24 58.55-92.75 28.4a17.015 17.015 0 0 0-11.28 21.23l134.08 437.93a17.03 17.03 0 0 0 16.26 12.03 16.8 16.8 0 0 0 4.97-.75l63.58-19.46 2-.62v-2.09l-2 .61-64.17 19.65a15.015 15.015 0 0 1-18.73-9.95L2.666 136.734a14.98 14.98 0 0 1 9.95-18.73l92.75-28.4 191.24-58.54 92.75-28.4a15.2 15.2 0 0 1 4.41-.66 15.015 15.015 0 0 1 14.32 10.61l39.05 127.56.62 2h2.08Z" fill="#3f3d56" />
299
+ <path d="M122.68 127.82a9.02 9.02 0 0 1-8.61-6.366l-12.88-42.072a9 9 0 0 1 5.97-11.24L283.1 14.278a9.01 9.01 0 0 1 11.24 5.971l12.88 42.072a9.01 9.01 0 0 1-5.97 11.241l-175.94 53.864a9 9 0 0 1-2.63.395" fill="#285c7c" />
300
+ <circle cx={190.154} cy={24.955} r={20} fill="#285c7c" />
301
+ <circle cx={190.154} cy={24.955} r={12.665} fill="#fff" />
302
+ <path d="M602.636 582.174h-338a8.51 8.51 0 0 1-8.5-8.5v-405a8.51 8.51 0 0 1 8.5-8.5h338a8.51 8.51 0 0 1 8.5 8.5v405a8.51 8.51 0 0 1-8.5 8.5" fill="#e6e6e6" />
303
+ <path d="M447.136 140.174h-210.5a17.024 17.024 0 0 0-17 17v407.8l2-.61v-407.19a15.02 15.02 0 0 1 15-15h211.12Zm183.5 0h-394a17.024 17.024 0 0 0-17 17v458a17.024 17.024 0 0 0 17 17h394a17.024 17.024 0 0 0 17-17v-458a17.024 17.024 0 0 0-17-17m15 475a15.02 15.02 0 0 1-15 15h-394a15.02 15.02 0 0 1-15-15v-458a15.02 15.02 0 0 1 15-15h394a15.02 15.02 0 0 1 15 15Z" fill="#3f3d56" />
304
+ <path d="M525.636 184.174h-184a9.01 9.01 0 0 1-9-9v-44a9.01 9.01 0 0 1 9-9h184a9.01 9.01 0 0 1 9 9v44a9.01 9.01 0 0 1-9 9" fill="#285c7c" />
305
+ <circle cx={433.636} cy={105.174} r={20} fill="#285c7c" />
306
+ <circle cx={433.636} cy={105.174} r={12.182} fill="#fff" />
307
+ </svg>
308
+ <p className="text-3xl text-primary-700">No GRN selected, Please select a GRN</p>
309
+ </div>
310
+ </div>
311
+ );
312
+ }
313
+ };
314
+
315
+ export default GRNDetailPage;
vafront/src/Pages/HomePage.jsx ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react";
2
+
3
+ function HomePage() {
4
+ return (
5
+ <div className="flex flex-col gap-10 items-center justify-center w-full h-full opacity-80">
6
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 820.615 714.558" className="w-[50%] h-[50%]">
7
+ <path d="M519.033 169.224h-3.912V62.037A62.037 62.037 0 0 0 453.084 0h-227.09a62.037 62.037 0 0 0-62.037 62.037v588.035a62.037 62.037 0 0 0 62.037 62.036h227.09a62.037 62.037 0 0 0 62.037-62.036V245.52h3.912Z" fill="#3f3d56" />
8
+ <path fill="#3f3d56" d="M.244 682.871h718v2h-718z" />
9
+ <path d="M455.587 16.14h-29.643a22.01 22.01 0 0 1-20.378 30.323H275.469A22.01 22.01 0 0 1 255.09 16.14h-27.686a46.33 46.33 0 0 0-46.329 46.328V649.64a46.33 46.33 0 0 0 46.329 46.329h228.183a46.33 46.33 0 0 0 46.328-46.329V62.468a46.33 46.33 0 0 0-46.328-46.328" opacity={0.2} />
10
+ <path d="m71.563 684.765-1.074-.402c-.236-.09-23.708-9.082-34.704-29.474s-5.612-44.945-5.556-45.19l.253-1.118 1.073.402c.236.089 23.708 9.082 34.704 29.474s5.612 44.945 5.556 45.19ZM37.546 653.94c9.296 17.241 27.845 26.079 32.545 28.097.893-5.037 3.696-25.407-5.592-42.631-9.288-17.223-27.844-26.074-32.545-28.097-.894 5.04-3.696 25.407 5.592 42.63" fill="#3f3d56" />
11
+ <path d="M44.188 647.736c19.76 11.889 27.371 35.503 27.371 35.503s-24.427 4.339-44.188-7.55S0 640.186 0 640.186s24.428-4.339 44.188 7.55m194.479-417.849h43.962v10.583h-43.962zm180.731 0h15.468v10.583h-15.468zm30.936 0h15.468v10.583h-15.468zm-152.237 0h105.019v10.583H298.097zm65.942 68.385h15.468v10.583h-15.468zm30.936 0h15.468v10.583h-15.468zm-152.237 0h105.019v10.583H242.738zm122.115-44.776h43.962v10.583h-43.962zm59.43 0h43.962v10.583h-43.962zm-210.039 0h15.468v10.583h-15.468zm30.936 0h105.019v10.583H245.18zm72.454 33.378h-43.962v-10.583h43.962zm-59.429 0h-43.962v-10.583h43.962zm210.04 0h-15.468v-10.583h15.468zm-30.937 0H332.289v-10.583h105.019z" fill="#285c7c" />
12
+ <circle cx={341.495} cy={453.871} r={40} fill="#285c7c" />
13
+ <path d="M599.414 217.483c-11.607-19.612-34.57-20.526-34.57-20.526s-22.377-2.861-36.731 27.008c-13.38 27.841-31.845 54.722-2.973 61.24l5.215-16.232 3.23 17.44a113 113 0 0 0 12.353.21c30.92-.997 60.366.293 59.418-10.802-1.26-14.75 5.226-39.467-5.942-58.338" fill="#2f2e41" />
14
+ <path d="M557.615 254.417s15 21 6 38 21 35 21 35l22-48s-26-17-19-33Z" fill="#fbbebe" />
15
+ <circle cx={567.615} cy={237.417} r={26} fill="#fbbebe" />
16
+ <path d="m477.635 267.473 21.728-28.034s7.65-29.384 18.732-27.895-4.377 35.24-4.377 35.24l-21.59 31.03Zm109.98 372.944 7 37 15 4-4-44zm151-40 27 37 11 5 9-15-27-35z" fill="#fbbebe" />
17
+ <path d="m581.615 311.417-16.681-21.96s-32.32 5.96-35.32 8.96 8 58 8 58 2 15 11 23l9 6 74-15 2.783-32.926a86.4 86.4 0 0 0-22.782-66.074l-12.876 1.76Z" fill="#575a89" />
18
+ <path d="m533.615 300.417-5-2-23-2s-8-2-6-6 4-5 0-6-5-2-4-5 7-9 7-9l-17-14s-.92.651-2.408 1.855c-8.44 6.834-35.147 31.49-15.592 56.145 23 29 50 46 72 40Z" fill="#575a89" />
19
+ <path d="M555.615 380.417v14s-9 17-6 33 4 24 4 24a136.5 136.5 0 0 0 7 40c7 20-16 151 13 153s45 4 54-6-15-182-15-182 82 171 99 164 60-23 55-32-131-209-131-209l-4-9Zm48 290s-16-1-16 4-8 22-8 22-6 20 10 18 26-20 26-20l-4-19Zm167-35s-14-9-13-3 2 22 9 23 28 7 29 9 25 10 25-3-15-23-15-23l-17-13s-11-1-13 6-5 4-5 4" fill="#2f2e41" />
20
+ <circle cx={567.654} cy={197.057} r={16.604} fill="#2f2e41" />
21
+ <path d="M549.303 192.687a16.604 16.604 0 0 1 14.856-16.51 16.604 16.604 0 1 0 0 33.02 16.604 16.604 0 0 1-14.856-16.51" fill="#2f2e41" />
22
+ <path fill="#2f2e41" d="m594.282 215.593-22.686-11.884-31.33 4.862-6.481 28.628 16.135-.62 4.508-10.518v10.344l7.445-.286 4.321-16.745 2.701 17.825 26.468-.54z" />
23
+ <path d="m592.924 382.734-34.987.946s-29.854 5.809-28.18-6.24 30.8-7.836 30.8-7.836l31.88-4.863Z" fill="#fbbebe" />
24
+ <path d="M620.606 269.722a7.47 7.47 0 0 1 8.236 5.128c6.85 21.584 27.95 93.814 6.985 103.723-24.693 11.672-42.714 11.158-42.714 11.158l-9.645-23.748 8.78-8.24 9.375-60.275 4.492-25.55Z" fill="#575a89" />
25
+ <path opacity={0.4} d="m614.115 309.917-4 40-35 15 39-9z" />
26
+ </svg>
27
+ <p className="text-primary-700 text-4xl">Hi, Voice Assist is here to help.</p>
28
+ </div>
29
+ );
30
+ }
31
+
32
+ export default HomePage;
vafront/src/Pages/RollDetailPage.jsx ADDED
@@ -0,0 +1,384 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from "react";
2
+ import { useAtom } from "jotai";
3
+ import { CurrentRollAtom, VoiceAssistAtom, searchAtom, grnsAtom, CurrentGRNAtom, TranscribeAtom } from "../Variables";
4
+ import { useNavigate } from "react-router";
5
+
6
+ function RollDetailPage() {
7
+ const [name, setName] = useState("");
8
+ const [GRN, setGRN] = useState("");
9
+ const [rLength, setRLength] = useState("");
10
+ const [aLength, setALength] = useState("");
11
+ const [minWidth, setMinWidth] = useState("");
12
+ const [maxWidth, setMaxWidth] = useState("");
13
+ const [CS, setCS] = useState("");
14
+ const [LWV, setLWV] = useState("");
15
+ const [EPI, setEPI] = useState("");
16
+ const [PPI, setPPI] = useState("");
17
+ const [CutPcs, setCutPcs] = useState("");
18
+ const [sWarp, setSWarp] = useState("");
19
+ const [sWeft, setSWeft] = useState("");
20
+ const [GSM, setGSM] = useState("");
21
+ const [SL, setSL] = useState("");
22
+ const [SG, setSG] = useState("");
23
+ const [Bowing, setBowing] = useState("");
24
+ const [success, setSuccess] = useState(null);
25
+ const [error, setError] = useState(null);
26
+ const [search, setSearch] = useAtom(searchAtom);
27
+ const [currentRoll, setCurrentRoll] = useAtom(CurrentRollAtom);
28
+ const [grns, setGrns] = useAtom(grnsAtom);
29
+ const [transcribe, setTranscribe] = useAtom(TranscribeAtom);
30
+ const [currentGRN, setCurrentGRN] = useAtom(CurrentGRNAtom);
31
+ const [voiceAssist, setVoiceAssist] = useAtom(VoiceAssistAtom);
32
+ const navigate = useNavigate();
33
+ useEffect(() => {
34
+ if (currentRoll.name === "") {
35
+ voiceAssist.say("No roll selected, redirecting to home page", {
36
+ onEnd: () => {
37
+ navigate("/");
38
+ },
39
+ });
40
+ } else {
41
+ setName(currentRoll?.name || "");
42
+ setGRN(currentRoll?.GRN || "");
43
+ setRLength(currentRoll?.rLength || "");
44
+ setALength(currentRoll?.aLength || "");
45
+ setMinWidth(currentRoll?.minWidth || "");
46
+ setMaxWidth(currentRoll?.maxWidth || "");
47
+ setCS(currentRoll?.CS || "");
48
+ setLWV(currentRoll?.LWV || "");
49
+ setEPI(currentRoll?.EPI || "");
50
+ setPPI(currentRoll?.PPI || "");
51
+ setCutPcs(currentRoll?.CutPcs || "");
52
+ setSWarp(currentRoll?.sWarp || "");
53
+ setSWeft(currentRoll?.sWeft || "");
54
+ setGSM(currentRoll?.GSM || "");
55
+ setSL(currentRoll?.SL || "");
56
+ setSG(currentRoll?.SG || "");
57
+ setBowing(currentRoll?.Bowing || "");
58
+ }
59
+ }, [currentRoll, navigate, voiceAssist]);
60
+
61
+ const handleSubmit = () => {
62
+ // if (!name || !GRN || !rLength || !aLength || !minWidth || !maxWidth || !CS || !LWV || !EPI || !PPI || !CutPcs || !sWarp || !sWeft || !GSM || !SL || !SG || !Bowing) {
63
+ // setError("Please fill all the fields");
64
+ // setTimeout(() => setError(null), 3000);
65
+ // return;
66
+ // }
67
+
68
+ const data = new FormData();
69
+ if (rLength !== "") data.append("rLength", rLength);
70
+ if (aLength !== "") data.append("aLength", aLength);
71
+ if (minWidth !== "") data.append("minWidth", minWidth);
72
+ if (maxWidth !== "") data.append("maxWidth", maxWidth);
73
+ if (CS !== "") data.append("CS", CS);
74
+ if (LWV !== "") data.append("LWV", LWV);
75
+ if (EPI !== "") data.append("EPI", EPI);
76
+ if (PPI !== "") data.append("PPI", PPI);
77
+ if (CutPcs !== "") data.append("CutPcs", CutPcs);
78
+ if (sWarp !== "") data.append("sWarp", sWarp);
79
+ if (sWeft !== "") data.append("sWeft", sWeft);
80
+ if (GSM !== "") data.append("GSM", GSM);
81
+ if (SL !== "") data.append("SL", SL);
82
+ if (SG !== "") data.append("SG", SG);
83
+ if (Bowing !== "") data.append("Bowing", Bowing);
84
+
85
+ fetch(`/api/rollUpdate/${currentRoll?.name}`, {
86
+ method: "POST",
87
+ body: data,
88
+ })
89
+ .then((response) => response.json())
90
+ .then((data) => {
91
+ if (data.status === "success") {
92
+ setSuccess(data.msg);
93
+ setTimeout(() => setSuccess(null), 3000);
94
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: data.msg, isCommand: true }]);
95
+ voiceAssist.say(data.msg);
96
+ navigate("/grn");
97
+ } else {
98
+ setError(data.msg);
99
+ setTimeout(() => setError(null), 3000);
100
+ voiceAssist.say(data.msg);
101
+ }
102
+ })
103
+ .catch((error) => {console.error("Error:", error);window.location.href = "/";});
104
+ };
105
+
106
+ useEffect(() => {
107
+ voiceAssist.emptyCommands();
108
+ voiceAssist.on(["open *", "grn *", "open grn *"], true).then((i, wildcard) => {
109
+ wildcard = wildcard.replace(/\s/g, "");
110
+ let found = false;
111
+ for (let index = 0; index < grns.length; index++) {
112
+ if (grns[index].GRN.toLowerCase() == wildcard.toLowerCase()) {
113
+ setCurrentGRN(grns[index]);
114
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "open GRN " + wildcard, isCommand: true }]);
115
+ navigate("/grn");
116
+ localStorage.setItem("currentGRN", JSON.stringify(grns[index]));
117
+ found = true;
118
+ }
119
+ }
120
+ if (!found) {
121
+ voiceAssist.say("No GRN found with that Number");
122
+ }
123
+ });
124
+ voiceAssist.on(["search *"], true).then((i, wildcard) => {
125
+ wildcard = wildcard.replace(/ /g, "");
126
+ setSearch(wildcard);
127
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "search " + wildcard, isCommand: true }]);
128
+ });
129
+ voiceAssist.on(["transcribe"]).then((i) => {
130
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "transcribe", isCommand: true }]);
131
+ navigate("/transcribe");
132
+ });
133
+ voiceAssist.on(["home", "go to home"]).then((i) => {
134
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "home", isCommand: true }]);
135
+ navigate("/");
136
+ });
137
+ voiceAssist.on(["refresh"]).then((i) => {
138
+ window.location.reload();
139
+ });
140
+ voiceAssist.on(["A1 *", "A 1 *", "a1 *", "a 1 *", "A1*", "A 1*", "a1*", "a 1*"], true).then((i, wildcard) => {
141
+ setRLength(parseFloat(wildcard));
142
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Roll Length Updated to " + parseFloat(wildcard), isCommand: true }]);
143
+ });
144
+ voiceAssist.on(["A2 *", "A 2 *", "a 2 *", "a2 *", "A2*", "A 2*", "a 2*", "a2*"], true).then((i, wildcard) => {
145
+ setALength(parseFloat(wildcard));
146
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Actual Length Updated to " + parseFloat(wildcard), isCommand: true }]);
147
+ });
148
+ voiceAssist.on(["B1 *", "B 1 *", "b 1 *", "b1 *", "B1*", "B 1*", "b 1*", "b1*"], true).then((i, wildcard) => {
149
+ setMinWidth(parseFloat(wildcard));
150
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Min Width Updated to " + parseFloat(wildcard), isCommand: true }]);
151
+ });
152
+ voiceAssist.on(["B2 *", "B 2 *", "b 2 *", "b2 *", "B2*", "B 2*", "b 2*", "b2*"], true).then((i, wildcard) => {
153
+ setMaxWidth(parseFloat(wildcard));
154
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Max Width Updated to " + parseFloat(wildcard), isCommand: true }]);
155
+ });
156
+ voiceAssist.on(["B3 *", "B 3 *", "b 3 *", "b3 *", "B3*", "B 3*", "b 3*", "b3*"], true).then((i, wildcard) => {
157
+ setCS(wildcard);
158
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "CS Updated to " + wildcard, isCommand: true }]);
159
+ });
160
+ voiceAssist.on(["B5 *", "B 5 *", "b 5 *", "b5 *", "B5*", "B 5*", "b 5*", "b5*"], true).then((i, wildcard) => {
161
+ setLWV(wildcard);
162
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "LWV Updated to " + wildcard, isCommand: true }]);
163
+ });
164
+ voiceAssist.on(["D1 *", "D 1 *", "d 1 *", "d1 *", "D1*", "D 1*", "d 1*", "d1*"], true).then((i, wildcard) => {
165
+ setEPI(parseFloat(wildcard));
166
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "EPI Updated to " + parseFloat(wildcard), isCommand: true }]);
167
+ });
168
+ voiceAssist.on(["D2 *", "D 2 *", "d 2 *", "d2 *", "D2*", "D 2*", "d 2*", "d2*"], true).then((i, wildcard) => {
169
+ setPPI(parseFloat(wildcard));
170
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "PPI Updated to " + parseFloat(wildcard), isCommand: true }]);
171
+ });
172
+ voiceAssist.on(["D3 *", "D 3 *", "d 3 *", "d3 *", "D3*", "D 3*", "d 3*", "d3*"], true).then((i, wildcard) => {
173
+ setCutPcs(parseFloat(wildcard));
174
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Cut Pcs Updated to " + parseFloat(wildcard), isCommand: true }]);
175
+ });
176
+ voiceAssist.on(["D4 *", "D 4 *", "d 4 *", "d4 *", "D4*", "D 4*", "d 4*", "d4*"], true).then((i, wildcard) => {
177
+ setSWarp(wildcard);
178
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Shrinkage Warp Updated to " + wildcard, isCommand: true }]);
179
+ });
180
+ voiceAssist.on(["F1 *", "F 1 *", "f 1 *", "f1 *", "F1*", "F 1*", "f 1*", "f1*"], true).then((i, wildcard) => {
181
+ setSWeft(wildcard);
182
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Shrinkage Weft Updated to " + wildcard, isCommand: true }]);
183
+ });
184
+ voiceAssist.on(["F2 *", "F 2 *", "f 2 *", "f2 *", "F2*", "F 2*", "f 2*", "f2*"], true).then((i, wildcard) => {
185
+ setGSM(parseFloat(wildcard));
186
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "GSM Updated to " + parseFloat(wildcard), isCommand: true }]);
187
+ });
188
+ voiceAssist.on(["F3 *", "F 3 *", "f 3 *", "f3 *", "F3*", "F 3*", "f 3*", "f3*"], true).then((i, wildcard) => {
189
+ setSL(wildcard);
190
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "SL Updated to " + wildcard, isCommand: true }]);
191
+ });
192
+ voiceAssist.on(["F4 *", "F 4 *", "f 4 *", "f4 *", "F4*", "F 4*", "f 4*", "f4*"], true).then((i, wildcard) => {
193
+ setSG(wildcard);
194
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "SG Updated to " + wildcard, isCommand: true }]);
195
+ });
196
+ voiceAssist.on(["F5 *", "F 5 *", "f 5 *", "f5 *", "F5*", "F 5*", "f 5*", "f5*"], true).then((i, wildcard) => {
197
+ setBowing(wildcard);
198
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "Bowing Updated to " + wildcard, isCommand: true }]);
199
+ });
200
+ voiceAssist.on(["update", "submit"]).then((i) => {
201
+ console.log("submitting");
202
+ submitBtn.click();
203
+ });
204
+ voiceAssist.on(["clear all", "clear"]).then((i) => {
205
+ setRLength("");
206
+ setALength("");
207
+ setMinWidth("");
208
+ setMaxWidth("");
209
+ setCS("");
210
+ setLWV("");
211
+ setEPI("");
212
+ setPPI("");
213
+ setCutPcs("");
214
+ setSWarp("");
215
+ setSWeft("");
216
+ setGSM("");
217
+ setSL("");
218
+ setSG("");
219
+ setBowing("");
220
+ setTranscribe((prev) => [...prev.slice(0, -1), { msg: "clear all", isCommand: true }]);
221
+ });
222
+ console.log("Commands", voiceAssist?.getAvailableCommands().length);
223
+ }, [voiceAssist]);
224
+
225
+ return (
226
+ <div className="w-full h-fit min-h-[calc(100vh-4.1rem)] overflow-y-auto custom-scrollbar flex items-center justify-center">
227
+ {currentRoll.name !== "" && (
228
+ <div className="relative flex gap-10 bg-clip-border rounded-xl bg-white text-gray-700 w-full max-w-[48rem] flex-row">
229
+ <div className="relative flex flex-col bg-clip-border rounded-xl bg-transparent text-primary-700 shadow-none">
230
+ {success && (
231
+ <div role="alert" className="relative w-full text-base font-regular px-4 py-4 mt-3 rounded-none border-l-4 border-green-600 bg-green-600/10 font-medium text-green-600 flex" style={{ opacity: 1 }}>
232
+ <div className="shrink-0">
233
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="h-6 w-6">
234
+ <path fillRule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm13.36-1.814a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z" clipRule="evenodd" />
235
+ </svg>
236
+ </div>
237
+ <div className="ml-3 mr-12 truncate" id="successMsg">
238
+ {success}
239
+ </div>
240
+ </div>
241
+ )}
242
+ {error && (
243
+ <div role="alert" className="relative w-full text-base font-regular px-4 py-4 mt-3 rounded-none border-l-4 border-red-500 bg-red-500/10 font-medium text-red-500 flex" style={{ opacity: 1 }}>
244
+ <div className="shrink-0">
245
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="h-6 w-6">
246
+ <path fillRule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm13.36-1.814a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z" clipRule="evenodd" />
247
+ </svg>
248
+ </div>
249
+ <div className="ml-3 mr-12 truncate" id="errorMsg">
250
+ {error}
251
+ </div>
252
+ </div>
253
+ )}
254
+
255
+ <div className="mt-8 mb-2 lg:w-full w-[80%] lg:mx-0 mx-auto">
256
+ <div className="mb-1 grid grid-cols-2 md:grid-cols-4 gap-3">
257
+ <div>
258
+ <h6 className="font-semibold text-primary-900 mb-3">Name</h6>
259
+ <input onChange={(event) => setName(event.target.value)} value={name} disabled placeholder="Name" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
260
+ </div>
261
+ <div>
262
+ <h6 className="font-semibold text-primary-900 mb-3">GRN</h6>
263
+ <input onChange={(event) => setGRN(event.target.value)} value={GRN} disabled placeholder="GRN" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
264
+ </div>
265
+ <div>
266
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
267
+ Roll Length <span className="bg-primary-200 font-normal p-1 rounded">(A1)</span>
268
+ </h6>
269
+ <input onChange={(event) => setRLength(event.target.value)} value={rLength} placeholder="Roll Length" type="number" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
270
+ </div>
271
+ <div>
272
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
273
+ Actual Length <span className="bg-primary-200 font-normal p-1 rounded">(A2)</span>
274
+ </h6>
275
+ <input onChange={(event) => setALength(event.target.value)} value={aLength} placeholder="Actual Length" type="number" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
276
+ </div>
277
+ <div>
278
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
279
+ Min Width <span className="bg-primary-200 font-normal p-1 rounded">(B1)</span>
280
+ </h6>
281
+ <input onChange={(event) => setMinWidth(event.target.value)} value={minWidth} placeholder="Min Width" type="number" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
282
+ </div>
283
+ <div>
284
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
285
+ Max Width <span className="bg-primary-200 font-normal p-1 rounded">(B2)</span>
286
+ </h6>
287
+ <input onChange={(event) => setMaxWidth(event.target.value)} value={maxWidth} placeholder="Max Width" type="number" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
288
+ </div>
289
+ <div>
290
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
291
+ CS <span className="bg-primary-200 font-normal p-1 rounded">(B3)</span>
292
+ </h6>
293
+ <input onChange={(event) => setCS(event.target.value)} value={CS} placeholder="CS" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
294
+ </div>
295
+ <div>
296
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
297
+ LWV <span className="bg-primary-200 font-normal p-1 rounded">(B5)</span>
298
+ </h6>
299
+ <input onChange={(event) => setLWV(event.target.value)} value={LWV} placeholder="LWV" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
300
+ </div>
301
+ <div>
302
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
303
+ EPI <span className="bg-primary-200 font-normal p-1 rounded">(D1)</span>
304
+ </h6>
305
+ <input onChange={(event) => setEPI(event.target.value)} value={EPI} placeholder="EPI" type="number" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
306
+ </div>
307
+ <div>
308
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
309
+ PPI <span className="bg-primary-200 font-normal p-1 rounded">(D2)</span>
310
+ </h6>
311
+ <input onChange={(event) => setPPI(event.target.value)} value={PPI} placeholder="PPI" type="number" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
312
+ </div>
313
+ <div>
314
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
315
+ Cut Pcs <span className="bg-primary-200 font-normal p-1 rounded">(D3)</span>
316
+ </h6>
317
+ <input onChange={(event) => setCutPcs(event.target.value)} value={CutPcs} placeholder="Cut Pcs" type="number" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
318
+ </div>
319
+ <div>
320
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
321
+ Shinkage Warp <span className="bg-primary-200 font-normal p-1 rounded">(D4)</span>
322
+ </h6>
323
+ <input onChange={(event) => setSWarp(event.target.value)} value={sWarp} placeholder="sWarp" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
324
+ </div>
325
+ <div>
326
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
327
+ Shinkage Weft <span className="bg-primary-200 font-normal p-1 rounded">(F1)</span>
328
+ </h6>
329
+ <input onChange={(event) => setSWeft(event.target.value)} value={sWeft} placeholder="sWeft" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
330
+ </div>
331
+ <div>
332
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
333
+ GSM <span className="bg-primary-200 font-normal p-1 rounded">(F2)</span>
334
+ </h6>
335
+ <input onChange={(event) => setGSM(event.target.value)} value={GSM} placeholder="GSM" type="number" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
336
+ </div>
337
+ <div>
338
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
339
+ SL <span className="bg-primary-200 font-normal p-1 rounded">(F3)</span>
340
+ </h6>
341
+ <input onChange={(event) => setSL(event.target.value)} value={SL} placeholder="SL" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
342
+ </div>
343
+ <div>
344
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
345
+ SG <span className="bg-primary-200 font-normal p-1 rounded">(F4)</span>
346
+ </h6>
347
+ <input onChange={(event) => setSG(event.target.value)} value={SG} placeholder="SG" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
348
+ </div>
349
+ <div className="col-span-2">
350
+ <h6 className="font-semibold text-primary-900 mb-1 flex items-center justify-between">
351
+ Bowing <span className="bg-primary-200 font-normal p-1 rounded">(F5)</span>
352
+ </h6>
353
+ <input onChange={(event) => setBowing(event.target.value)} value={Bowing} placeholder="Bowing" type="text" className="w-full h-11 bg-transparent text-primary-700 font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border border focus:border-2 border-t-transparent focus:border-t-transparent text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900 !border-t-blue-gray-200 focus:!border-t-gray-900" />
354
+ </div>
355
+ </div>
356
+ <button id="submitBtn" onClick={handleSubmit} className="align-middle select-none font-sans font-bold text-center uppercase transition-all disabled:opacity-50 disabled:shadow-none disabled:pointer-events-none text-xs py-3 px-6 rounded-lg bg-gradient-to-tr from-primary-950 to-primary-800 text-white shadow-md shadow-gray-900/10 hover:shadow-lg hover:shadow-gray-900/20 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none block w-full mt-6" type="button">
357
+ Update
358
+ </button>
359
+ </div>
360
+ </div>
361
+ </div>
362
+ )}
363
+ {currentRoll.name === "" && (
364
+ <div className="flex flex-col items-center justify-center gap-5">
365
+ <svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 647.636 632.174" className="w-[50%] h-[50%] opacity-80">
366
+ <path d="M411.146 142.174h-174.51a15.02 15.02 0 0 0-15 15v387.85l-2 .61-42.81 13.11a8.007 8.007 0 0 1-9.99-5.31l-127.34-415.95a8.003 8.003 0 0 1 5.31-9.99l65.97-20.2 191.25-58.54 65.97-20.2a7.99 7.99 0 0 1 9.99 5.3l32.55 106.32Z" fill="#f2f2f2" />
367
+ <path d="m449.226 140.174-39.23-128.14a16.994 16.994 0 0 0-21.23-11.28l-92.75 28.39-191.24 58.55-92.75 28.4a17.015 17.015 0 0 0-11.28 21.23l134.08 437.93a17.03 17.03 0 0 0 16.26 12.03 16.8 16.8 0 0 0 4.97-.75l63.58-19.46 2-.62v-2.09l-2 .61-64.17 19.65a15.015 15.015 0 0 1-18.73-9.95L2.666 136.734a14.98 14.98 0 0 1 9.95-18.73l92.75-28.4 191.24-58.54 92.75-28.4a15.2 15.2 0 0 1 4.41-.66 15.015 15.015 0 0 1 14.32 10.61l39.05 127.56.62 2h2.08Z" fill="#3f3d56" />
368
+ <path d="M122.68 127.82a9.02 9.02 0 0 1-8.61-6.366l-12.88-42.072a9 9 0 0 1 5.97-11.24L283.1 14.278a9.01 9.01 0 0 1 11.24 5.971l12.88 42.072a9.01 9.01 0 0 1-5.97 11.241l-175.94 53.864a9 9 0 0 1-2.63.395" fill="#285c7c" />
369
+ <circle cx={190.154} cy={24.955} r={20} fill="#285c7c" />
370
+ <circle cx={190.154} cy={24.955} r={12.665} fill="#fff" />
371
+ <path d="M602.636 582.174h-338a8.51 8.51 0 0 1-8.5-8.5v-405a8.51 8.51 0 0 1 8.5-8.5h338a8.51 8.51 0 0 1 8.5 8.5v405a8.51 8.51 0 0 1-8.5 8.5" fill="#e6e6e6" />
372
+ <path d="M447.136 140.174h-210.5a17.024 17.024 0 0 0-17 17v407.8l2-.61v-407.19a15.02 15.02 0 0 1 15-15h211.12Zm183.5 0h-394a17.024 17.024 0 0 0-17 17v458a17.024 17.024 0 0 0 17 17h394a17.024 17.024 0 0 0 17-17v-458a17.024 17.024 0 0 0-17-17m15 475a15.02 15.02 0 0 1-15 15h-394a15.02 15.02 0 0 1-15-15v-458a15.02 15.02 0 0 1 15-15h394a15.02 15.02 0 0 1 15 15Z" fill="#3f3d56" />
373
+ <path d="M525.636 184.174h-184a9.01 9.01 0 0 1-9-9v-44a9.01 9.01 0 0 1 9-9h184a9.01 9.01 0 0 1 9 9v44a9.01 9.01 0 0 1-9 9" fill="#285c7c" />
374
+ <circle cx={433.636} cy={105.174} r={20} fill="#285c7c" />
375
+ <circle cx={433.636} cy={105.174} r={12.182} fill="#fff" />
376
+ </svg>
377
+ <p className="text-3xl text-primary-700">No roll selected, Please select a roll</p>
378
+ </div>
379
+ )}
380
+ </div>
381
+ );
382
+ }
383
+
384
+ export default RollDetailPage;
vafront/src/Pages/TranscribePage.jsx ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react";
2
+ import { useAtom } from "jotai";
3
+ import { TranscribeAtom } from "../Variables";
4
+
5
+ function TranscribePage() {
6
+ const [transcribe, setTranscribe] = useAtom(TranscribeAtom);
7
+ return (
8
+ <div className="p-5 pl-10 flex flex-col h-full">
9
+ <p className="text-xl font-semibold text-primary-950 mb-5">Transcript of speech</p>
10
+ <div className="h-full overflow-y-scroll noScrollBars">
11
+ {transcribe.map((item, index) => {
12
+ if (item?.isCommand) {
13
+ return (
14
+ <p key={index} className="bg-primary-100 rounded-lg p-2 my-1">
15
+ {`>>`} {item?.msg}
16
+ </p>
17
+ );
18
+ } else {
19
+ return (
20
+ <p key={index} className="">
21
+ {item?.msg}
22
+ </p>
23
+ );
24
+ }
25
+ })}
26
+ </div>
27
+ </div>
28
+ );
29
+ }
30
+
31
+ export default TranscribePage;
vafront/src/Variables.jsx ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { atom } from "jotai";
2
+ import Artyom from "artyom.js";
3
+
4
+ export const rollsAtom = atom([]);
5
+ export const grnsAtom = atom([]);
6
+ export const searchAtom = atom("");
7
+ export const VoiceAssistAtom = atom(new Artyom());
8
+ export const CurrentRollAtom = atom({
9
+ id: 1,
10
+ name: "",
11
+ supplierName: "",
12
+ description: "",
13
+ image: "",
14
+ stock: 0,
15
+ widthBefore: 0,
16
+ widthAfter: 0,
17
+ shrinkage: 0,
18
+ created_at: "",
19
+ updated_at: "",
20
+ });
21
+ export const CurrentGRNAtom = atom({
22
+ GRN: "",
23
+ quantity: "",
24
+ fabricDescription: "",
25
+ itemDescription: "",
26
+ fabricForm: "",
27
+ POWidth: 0,
28
+ POUOM: "",
29
+ PointsUOM: "",
30
+ Tolarence: 20.0,
31
+ color: "",
32
+ buyer: "",
33
+ supplier:"",
34
+ item:"",
35
+ supplierName:"",
36
+ PCH:"",
37
+ invoice:"",
38
+ fabricOdour:"",
39
+ PO:"",
40
+ basicUOM:"",
41
+ Warehouse:"",
42
+ convFactor:"",
43
+ created_at: "",
44
+ updated_at: "",
45
+ });
46
+ export const TranscribeAtom = atom([]);
vafront/src/assets/images/Symbol.svg ADDED
vafront/src/assets/images/blackLogo.svg ADDED
vafront/src/assets/images/whiteLogo.svg ADDED
vafront/src/assets/react.svg ADDED
vafront/src/index.css ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url("https://fonts.googleapis.com/css2?family=Epilogue:ital,wght@0,100..900;1,100..900&display=swap");
2
+
3
+ * {
4
+ font-family: "Epilogue", sans-serif;
5
+ }
6
+
7
+ .noScrollBars::-webkit-scrollbar {
8
+ display: none;
9
+ }
10
+
11
+ .custom-scrollbar::-webkit-scrollbar {
12
+ width: 10px;
13
+ }
14
+ .custom-scrollbar::-webkit-scrollbar-track {
15
+ background: #f1f1f1;
16
+ }
17
+ .custom-scrollbar::-webkit-scrollbar-thumb {
18
+ background: #285c7c;
19
+ }
20
+
21
+ .truncate3 {
22
+ display: -webkit-box;
23
+ -webkit-line-clamp: 3;
24
+ -webkit-box-orient: vertical;
25
+ overflow: hidden;
26
+ }
27
+
28
+ @tailwind base;
29
+ @tailwind components;
30
+ @tailwind utilities;
vafront/src/main.jsx ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App.jsx";
4
+ import { BrowserRouter as Router } from "react-router-dom";
5
+ import "./index.css";
6
+
7
+ ReactDOM.createRoot(document.getElementById("root")).render(
8
+ <Router>
9
+ <App />
10
+ </Router>
11
+ );
vafront/tailwind.config.js ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const withMT = require("@material-tailwind/react/utils/withMT");
2
+ /** @type {import('tailwindcss').Config} */
3
+ export default withMT({
4
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}", "./node_modules/@material-tailwind/react/components/**/*.{js,ts,jsx,tsx}", "./node_modules/@material-tailwind/react/theme/components/**/*.{js,ts,jsx,tsx}"],
5
+ theme: {
6
+ extend: {
7
+ colors: {
8
+ primary: { 50: "#f4f8fb", 100: "#e7f1f7", 200: "#cae0ed", 300: "#9bc6de", 400: "#65a8cb", 500: "#3d84a8", 600: "#317298", 700: "#285c7c", 800: "#254e67", 900: "#234357", 950: "#172b3a" },
9
+ base: "#e6e6e6",
10
+ },
11
+ },
12
+ },
13
+ plugins: [],
14
+ });
vafront/vite.config.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+
4
+ // https://vitejs.dev/config/
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ server: {
8
+ proxy: {
9
+ "/api": {
10
+ target: "http://127.0.0.1:8000",
11
+ changeOrigin: true,
12
+ secure: false,
13
+ },
14
+ "/media": {
15
+ target: "http://127.0.0.1:8000",
16
+ changeOrigin: true,
17
+ secure: false,
18
+ },
19
+ },
20
+ },
21
+ });