folder structure refactor

This commit is contained in:
2025-08-06 10:27:21 +05:30
parent 498bda216b
commit 49a64062af
732 changed files with 48173 additions and 48163 deletions

9
app/src/app.test.tsx Normal file
View File

@@ -0,0 +1,9 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import App from "./app";
test("renders learn react link", () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

30
app/src/app.tsx Normal file
View File

@@ -0,0 +1,30 @@
import React, { useEffect } from "react";
import { Cache } from "three";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Dashboard from "./pages/Dashboard";
import Project from "./pages/Project";
import UserAuth from "./pages/UserAuth";
import "./styles/main.scss";
import { LoggerProvider } from "./components/ui/log/LoggerContext";
const App: React.FC = () => {
useEffect(() => {
Cache.clear();
Cache.enabled = true;
}, []);
return (
<LoggerProvider>
<Router>
<Routes>
<Route path="/" element={<UserAuth />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/:projectId" element={<Project />} />
</Routes>
</Router>
</LoggerProvider>
);
};
export default App;

View File

@@ -0,0 +1,6 @@
<svg width="11" height="14" viewBox="0 0 11 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.7069 1.10756L1.75387 1.07218C2.70246 0.400484 3.83125 0.029837 4.94625 0.0104403C6.35793 -0.0822458 7.7395 0.447354 8.6564 1.3938C9.60485 2.19356 10.1085 3.40227 10.0118 4.55497C10.0147 5.42501 9.73379 6.27227 9.18619 7.00095C8.7929 7.48237 8.33582 7.90794 7.8818 8.22485L7.33801 8.66584C7.21154 8.76481 7.11492 8.89685 7.07561 8.99858C7.01588 9.14321 7.0229 9.37843 7.03176 9.57272V10.6183L3.03176 10.6183L3.01404 9.68567C2.96765 8.99886 3.00577 8.30894 3.14296 7.56046C3.24087 7.17773 3.44043 6.85713 3.73311 6.55348C3.93171 6.34743 4.07945 6.22479 4.55212 5.85341L5.14921 5.38276C5.30838 5.26567 5.45215 5.12897 5.52912 5.03974C5.63134 4.89184 5.69179 4.71911 5.70207 4.58361C5.70517 4.45782 5.66343 4.33503 5.54207 4.18109C5.42185 4.00905 5.21682 3.917 4.94703 3.94676C4.69233 3.96086 4.45265 4.07176 4.3048 4.22627C4.12283 4.43453 4.01908 4.69968 4.01138 4.97613L3.9843 5.94829H0.0899556L0.0150696 5.02953C-0.107782 3.52229 0.526244 2.0525 1.7069 1.10756Z" fill="white"/>
<path d="M2.33157 1.88826C3.11632 1.33258 4.05015 1.02594 5.01157 1.00826C6.13158 0.934725 7.22769 1.3549 8.01156 2.15826C8.71302 2.74975 9.0855 3.64369 9.01156 4.55826C9.01373 5.21079 8.80309 5.84624 8.41157 6.36826C8.07577 6.7793 7.68551 7.14265 7.25157 7.44826L6.72157 7.87826C6.44972 8.09098 6.24205 8.37479 6.12157 8.69826C6.05795 8.88813 6.01736 9.30693 6.03157 9.61826H4.03156C3.9907 9.01311 4.00428 8.40523 4.11156 7.80826C4.22156 7.37826 4.61157 7.07826 5.17157 6.63826L5.74157 6.18826C5.96848 6.02134 6.17343 5.82647 6.35157 5.60826C6.55601 5.31245 6.67692 4.967 6.70157 4.60826C6.71053 4.24514 6.59001 3.89067 6.36157 3.60826C6.03044 3.13441 5.46571 2.88085 4.89157 2.94826C4.38217 2.97645 3.90281 3.19825 3.55156 3.56826C3.21667 3.95153 3.02574 4.43949 3.01156 4.94826H1.01157C0.919144 3.80505 1.38474 2.68762 2.26157 1.94826" fill="black"/>
<path d="M7.03125 10.0078V14.0078H3.03125V10.0078H7.03125Z" fill="white"/>
<path d="M6.03125 11.0078H4.03125V13.0078H6.03125V11.0078Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,4 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 5H14V9H9V14H5V9H0V5H5V0H9V5Z" fill="black"/>
<path d="M8 6H13V8H8V13H6V8H1V6H6V1H8V6Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 217 B

View File

@@ -0,0 +1,7 @@
<svg width="15" height="13" viewBox="0 0 15 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.57009 1.77983C4.05009 1.59983 5.00009 1.70983 5.25009 2.24983C5.50009 2.78983 5.65009 3.48983 5.66009 3.31983C5.64096 2.80313 5.68461 2.28602 5.79009 1.77983C5.90124 1.45565 6.15591 1.20098 6.48009 1.08983C6.77741 0.995805 7.09308 0.975217 7.40009 1.02983C7.71051 1.09373 7.98544 1.27226 8.17009 1.52983C8.40404 2.11296 8.53596 2.73199 8.56009 3.35983C8.58497 2.82409 8.67565 2.29344 8.83009 1.77983C8.9972 1.54438 9.24123 1.37462 9.52009 1.29983C9.85069 1.23939 10.1895 1.23939 10.5201 1.29983C10.7915 1.38989 11.0288 1.56089 11.2001 1.78983C11.4125 2.31998 11.5407 2.88008 11.5801 3.44983C11.5801 3.58983 11.6501 3.05983 11.8701 2.70983C12.0468 2.18516 12.6154 1.9031 13.1401 2.07983C13.6648 2.25656 13.9468 2.82516 13.7701 3.34983C13.7701 3.99983 13.7701 3.96983 13.7701 4.40983C13.7701 4.84983 13.7701 5.23983 13.7701 5.60983C13.7341 6.19505 13.6538 6.77671 13.5301 7.34983C13.3565 7.85715 13.1143 8.33829 12.8101 8.77983C12.3247 9.31989 11.9235 9.93009 11.6201 10.5898C11.5461 10.9178 11.5125 11.2537 11.5201 11.5898C11.5191 11.9005 11.5594 12.2099 11.6401 12.5098C11.2313 12.5535 10.8189 12.5535 10.4101 12.5098C10.0201 12.4498 9.54009 11.6698 9.41009 11.4298C9.34577 11.301 9.21412 11.2195 9.07009 11.2195C8.92607 11.2195 8.79442 11.301 8.73009 11.4298C8.51009 11.8098 8.02009 12.4998 7.73009 12.5398C7.06009 12.6198 5.67009 12.5398 4.59009 12.5398C4.59009 12.5398 4.78009 11.5398 4.36009 11.1798C3.94009 10.8198 3.53009 10.3998 3.22009 10.1198L2.39009 9.19983C1.80478 8.65651 1.37647 7.96569 1.15009 7.19983C0.940094 6.25983 0.960094 5.80983 1.15009 5.42983C1.34388 5.11604 1.64649 4.88464 2.00009 4.77983C2.29386 4.72654 2.59628 4.74716 2.88009 4.83983C3.07636 4.922 3.24598 5.05701 3.37009 5.22983C3.60009 5.53983 3.68009 5.68983 3.58009 5.34983C3.48009 5.00983 3.26009 4.75983 3.15009 4.34983C2.93595 3.86563 2.80737 3.34796 2.77009 2.81983C2.81108 2.346 3.14192 1.9474 3.60009 1.81983" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.57009 1.77983C4.05009 1.59983 5.00009 1.70983 5.25009 2.24983C5.50009 2.78983 5.65009 3.48983 5.66009 3.31983C5.64096 2.80313 5.68461 2.28602 5.79009 1.77983C5.90124 1.45565 6.15591 1.20098 6.48009 1.08983C6.77741 0.995805 7.09308 0.975217 7.40009 1.02983C7.71051 1.09373 7.98544 1.27226 8.17009 1.52983C8.40404 2.11296 8.53596 2.73199 8.56009 3.35983C8.58497 2.82409 8.67565 2.29344 8.83009 1.77983C8.9972 1.54438 9.24123 1.37462 9.52009 1.29983C9.85069 1.23939 10.1895 1.23939 10.5201 1.29983C10.7915 1.38989 11.0288 1.56089 11.2001 1.78983C11.4125 2.31998 11.5407 2.88008 11.5801 3.44983C11.5801 3.58983 11.6501 3.05983 11.8701 2.70983C12.0468 2.18516 12.6154 1.9031 13.1401 2.07983C13.6648 2.25656 13.9468 2.82516 13.7701 3.34983C13.7701 3.99983 13.7701 3.96983 13.7701 4.40983C13.7701 4.84983 13.7701 5.23983 13.7701 5.60983C13.7341 6.19505 13.6538 6.77671 13.5301 7.34983C13.3565 7.85715 13.1143 8.33829 12.8101 8.77983C12.3247 9.31989 11.9235 9.93009 11.6201 10.5898C11.5461 10.9178 11.5125 11.2537 11.5201 11.5898C11.5191 11.9005 11.5594 12.2099 11.6401 12.5098C11.2313 12.5535 10.8189 12.5535 10.4101 12.5098C10.0201 12.4498 9.54009 11.6698 9.41009 11.4298C9.34577 11.301 9.21412 11.2195 9.07009 11.2195C8.92607 11.2195 8.79442 11.301 8.73009 11.4298C8.51009 11.8098 8.02009 12.4998 7.73009 12.5398C7.06009 12.6198 5.67009 12.5398 4.59009 12.5398C4.59009 12.5398 4.78009 11.5398 4.36009 11.1798C3.94009 10.8198 3.53009 10.3998 3.22009 10.1198L2.39009 9.19983C1.80478 8.65651 1.37647 7.96569 1.15009 7.19983C0.940094 6.25983 0.960094 5.80983 1.15009 5.42983C1.34388 5.11604 1.64649 4.88464 2.00009 4.77983C2.29386 4.72654 2.59628 4.74716 2.88009 4.83983C3.07636 4.922 3.24598 5.05701 3.37009 5.22983C3.60009 5.53983 3.68009 5.68983 3.58009 5.34983C3.48009 5.00983 3.26009 4.75983 3.15009 4.34983C2.93595 3.86563 2.80737 3.34796 2.77009 2.81983C2.79054 2.33907 3.11066 1.92291 3.57009 1.77983Z" stroke="black" stroke-width="0.75" stroke-linejoin="round"/>
<path d="M11.3203 9.4548V6.00302C11.3203 5.7964 11.1524 5.62891 10.9453 5.62891C10.7382 5.62891 10.5703 5.7964 10.5703 6.00302V9.4548C10.5703 9.66141 10.7382 9.82891 10.9453 9.82891C11.1524 9.82891 11.3203 9.66141 11.3203 9.4548Z" fill="black"/>
<path d="M9.34031 9.45353L9.32031 5.99998C9.31911 5.79386 9.15025 5.62772 8.94315 5.62891C8.73605 5.6301 8.56913 5.79816 8.57032 6.00428L8.59032 9.45783C8.59151 9.66396 8.76037 9.83009 8.96747 9.8289C9.17458 9.82771 9.3415 9.65965 9.34031 9.45353Z" fill="black"/>
<path d="M6.57032 6.00881L6.59032 9.45342C6.59153 9.66201 6.7604 9.83012 6.96751 9.8289C7.17461 9.82768 7.34152 9.65759 7.34031 9.449L7.32031 6.0044C7.3191 5.7958 7.15022 5.62769 6.94312 5.62891C6.73602 5.63013 6.56911 5.80022 6.57032 6.00881Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 1C11.866 1 15 4.13401 15 8C15 11.866 11.866 15 8 15H2C1.44772 15 1 14.5523 1 14V8C1 4.13401 4.13401 1 8 1Z" fill="black" stroke="white" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 270 B

View File

@@ -0,0 +1,4 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.99 6V0H6.01V6H0V9H6.01V15H8.99V9H15V6H8.99Z" fill="white"/>
<path d="M8 7V1H7V7H1V8H7V14H8V8H14V7H8Z" fill="#232020"/>
</svg>

After

Width:  |  Height:  |  Size: 234 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="20" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.70849 18.2848L6.01914 13.9573C6.20421 13.7715 6.45487 13.6658 6.71711 13.663L13.3181 13.5936C14.2439 13.5839 14.6604 12.4297 13.9542 11.8309L1.64669 1.39613C0.996961 0.845261 0 1.30706 0 2.15888V17.5791C0 18.4709 1.07909 18.9167 1.70849 18.2848Z" fill="white"/>
<path d="M1.30078 14.5353V5.02997C1.30078 4.17815 2.29774 3.71636 2.94747 4.26722L10.4817 10.655C11.1864 11.2525 10.7733 12.4042 9.84957 12.4177L5.94136 12.4746C5.66374 12.4787 5.40031 12.5979 5.21412 12.8039L3.04259 15.206C2.42871 15.885 1.30078 15.4507 1.30078 14.5353Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 665 B

View File

@@ -0,0 +1,4 @@
<svg width="10" height="15" viewBox="0 0 10 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.79999 0H0L3.28999 3.2L2.71999 3.83C2.35508 4.31517 2.02108 4.82284 1.71999 5.35C1.42677 5.99118 1.20219 6.66158 1.04999 7.35C0.993385 8.05887 0.993385 8.77113 1.04999 9.48C1.08712 10.0363 1.18777 10.5866 1.34999 11.12C1.50076 11.6048 1.71245 12.0685 1.97999 12.5C2.26031 12.9383 2.59647 13.3384 2.97999 13.69C3.66537 14.158 4.38776 14.5694 5.13999 14.92C4.76649 14.371 4.45144 13.7845 4.19999 13.17C4.07439 12.6664 3.98087 12.1554 3.91999 11.64C3.8692 11.1116 3.84917 10.5807 3.85999 10.05C3.87981 9.6673 3.94356 9.28814 4.04999 8.92C4.21288 8.44919 4.44912 8.00708 4.74999 7.61C4.9876 7.28231 5.25544 6.97764 5.54999 6.7C5.81776 6.43911 6.10165 6.1953 6.39999 5.97L9.79999 9.2V0Z" fill="white"/>
<path d="M8.79835 7V1H2.79835L4.64835 2.78C4.50835 2.93 4.31835 3.12 4.20835 3.26C3.92835 3.61 3.76835 3.8 3.59835 3.99C3.42835 4.18 3.33835 4.31 3.21835 4.46C3.08674 4.64242 2.96651 4.83278 2.85835 5.03C2.74835 5.23 2.62835 5.49 2.48835 5.78C2.3417 6.09919 2.23425 6.43497 2.16835 6.78C2.08885 7.10905 2.03204 7.44317 1.99835 7.78C1.98482 8.03315 1.98482 8.28685 1.99835 8.54C1.97451 8.87291 1.97451 9.20709 1.99835 9.54C2.08696 10.1309 2.24818 10.7086 2.47835 11.26L2.93835 12.19C2.84916 11.4334 2.80907 10.6718 2.81835 9.91C2.88962 9.31114 3.05499 8.72729 3.30835 8.18C3.35585 8.03336 3.41958 7.89249 3.49835 7.76L3.85835 7.19C4.06835 6.85 4.50835 6.32 4.61835 6.19C4.90945 5.86142 5.22358 5.55397 5.55835 5.27L6.34835 4.6L8.79835 7Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 0L0 8L5.22 13.22L8 16L16 8L8 0ZM6 11H5V10H6V11ZM6 6H5V5H6V6ZM11 11H10V10H11V11ZM10 5H11V6H10V5Z" fill="white"/>
<path d="M14.5502 7.98187L11.9902 5.17188V7.00187H7.99016H3.98016V5.17188L1.41016 7.98187L3.98016 10.7919V8.98187H7.99016H11.9902V10.7919L14.5502 7.98187Z" fill="black"/>
<path d="M8.97188 7.99187H8.98187V3.99188H10.7919L7.99187 1.42188L5.18187 3.99188H6.99187V7.99187V11.9919H5.17188L7.97187 14.5619L10.7819 11.9919H8.97188V7.99187Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@@ -0,0 +1,7 @@
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.98353 8.91984C4.88353 8.54984 4.78353 8.06984 4.57353 7.36984C4.36353 6.66984 4.23353 6.50984 4.10353 6.13984C3.97353 5.76984 3.80353 5.41984 3.60353 4.95984C3.42033 4.4899 3.2667 4.00896 3.14353 3.51984C3.06029 3.10764 3.1627 2.6797 3.42353 2.34984C3.78238 1.99966 4.30021 1.8664 4.78352 1.99984C5.16218 2.16543 5.4826 2.44057 5.70353 2.78984C5.99856 3.26151 6.24006 3.76462 6.42353 4.28984C6.70527 5.00947 6.90975 5.757 7.03352 6.51984L7.12353 6.96984C7.12353 6.96984 7.12353 5.84984 7.12353 5.80984C7.12353 4.80984 7.06353 3.98984 7.12353 2.86984C7.12353 2.73984 7.18353 2.27984 7.20353 2.14984C7.22938 1.7198 7.48564 1.33732 7.87353 1.14984C8.31881 0.950053 8.82824 0.950053 9.27353 1.14984C9.67213 1.32827 9.93818 1.71385 9.96352 2.14984C9.96352 2.25984 10.0535 3.14984 10.0535 3.25984C10.0535 4.25984 10.0535 4.89984 10.0535 5.42984C10.0535 5.65984 10.0535 7.05984 10.0535 6.89984C10.0771 5.5803 10.1907 4.26391 10.3935 2.95984C10.512 2.55128 10.7995 2.21285 11.1835 2.02984C11.6585 1.84278 12.198 1.93527 12.5835 2.26984C12.8717 2.58613 13.0413 2.99253 13.0635 3.41984C13.0635 3.82984 13.0635 4.31984 13.0635 4.66984C13.0635 5.53984 13.0635 5.98984 13.0635 6.78984C13.0635 6.78984 13.0635 7.08984 13.0635 6.96984C13.1535 6.68984 13.2535 6.42984 13.3335 6.22984C13.4135 6.02984 13.5735 5.61984 13.6935 5.36984C13.8156 5.1315 13.9526 4.90105 14.1035 4.67984C14.2604 4.42557 14.4955 4.22906 14.7735 4.11984C15.024 4.02302 15.3029 4.03099 15.5474 4.14197C15.7919 4.25294 15.9815 4.45758 16.0735 4.70984C16.1331 5.07409 16.1331 5.44559 16.0735 5.80984C16.0069 6.36927 15.8897 6.92152 15.7235 7.45984C15.5935 7.90984 15.4535 8.68984 15.3835 9.05984C15.3135 9.42984 15.1535 10.4398 15.0235 10.8798C14.831 11.4047 14.5651 11.8997 14.2335 12.3498C13.7483 12.8901 13.3472 13.5002 13.0435 14.1598C12.9688 14.4877 12.9352 14.8236 12.9435 15.1598C12.9419 15.4705 12.9823 15.78 13.0635 16.0798C12.6547 16.1234 12.2424 16.1234 11.8335 16.0798C11.4435 16.0198 10.9635 15.2398 10.8335 14.9998C10.7692 14.871 10.6376 14.7895 10.4935 14.7895C10.3495 14.7895 10.2178 14.871 10.1535 14.9998C9.92353 15.3798 9.44353 16.0698 9.10353 16.1098C8.43353 16.1898 7.05353 16.1098 5.96353 16.1098C5.96353 16.1098 6.15353 15.1098 5.73353 14.7498C5.31353 14.3898 4.90353 13.9698 4.59353 13.6898L3.76353 12.7698C3.48353 12.4098 3.13353 11.6798 2.52353 10.7698C2.17353 10.2698 1.52353 9.67984 1.24353 9.18984C1.00845 8.79216 0.940151 8.31767 1.05353 7.86984C1.22333 7.2752 1.81419 6.9043 2.42353 7.00984C2.88703 7.04038 3.32544 7.2313 3.66353 7.54984C3.93124 7.78148 4.18189 8.03213 4.41353 8.29984C4.57353 8.48984 4.61353 8.57984 4.79353 8.80984C4.97353 9.03984 5.09353 9.26984 5.00353 8.92984" fill="white"/>
<path d="M4.98353 8.91984C4.88353 8.54984 4.78353 8.06984 4.57353 7.36984C4.36353 6.66984 4.23353 6.50984 4.10353 6.13984C3.97353 5.76984 3.80353 5.41984 3.60353 4.95984C3.42033 4.4899 3.2667 4.00896 3.14353 3.51984C3.06029 3.10764 3.1627 2.6797 3.42353 2.34984C3.78238 1.99966 4.30021 1.8664 4.78352 1.99984C5.16218 2.16543 5.4826 2.44057 5.70353 2.78984C5.99856 3.26151 6.24006 3.76462 6.42353 4.28984C6.70527 5.00947 6.90975 5.757 7.03352 6.51984L7.12353 6.96984C7.12353 6.96984 7.12353 5.84984 7.12353 5.80984C7.12353 4.80984 7.06353 3.98984 7.12353 2.86984C7.12353 2.73984 7.18353 2.27984 7.20353 2.14984C7.22938 1.7198 7.48564 1.33732 7.87353 1.14984C8.31881 0.950053 8.82824 0.950053 9.27353 1.14984C9.67213 1.32827 9.93818 1.71385 9.96352 2.14984C9.96352 2.25984 10.0535 3.14984 10.0535 3.25984C10.0535 4.25984 10.0535 4.89984 10.0535 5.42984C10.0535 5.65984 10.0535 7.05984 10.0535 6.89984C10.0771 5.5803 10.1907 4.26391 10.3935 2.95984C10.512 2.55128 10.7995 2.21285 11.1835 2.02984C11.6585 1.84278 12.198 1.93527 12.5835 2.26984C12.8717 2.58613 13.0413 2.99253 13.0635 3.41984C13.0635 3.82984 13.0635 4.31984 13.0635 4.66984C13.0635 5.53984 13.0635 5.98984 13.0635 6.78984C13.0635 6.78984 13.0635 7.08984 13.0635 6.96984C13.1535 6.68984 13.2535 6.42984 13.3335 6.22984C13.4135 6.02984 13.5735 5.61984 13.6935 5.36984C13.8156 5.1315 13.9526 4.90105 14.1035 4.67984C14.2604 4.42557 14.4955 4.22906 14.7735 4.11984C15.024 4.02302 15.3029 4.03099 15.5474 4.14197C15.7919 4.25294 15.9815 4.45758 16.0735 4.70984C16.1331 5.07409 16.1331 5.44559 16.0735 5.80984C16.0069 6.36927 15.8897 6.92152 15.7235 7.45984C15.5935 7.90984 15.4535 8.68984 15.3835 9.05984C15.3135 9.42984 15.1535 10.4398 15.0235 10.8798C14.831 11.4047 14.5651 11.8997 14.2335 12.3498C13.7483 12.8901 13.3472 13.5002 13.0435 14.1598C12.9688 14.4877 12.9352 14.8236 12.9435 15.1598C12.9419 15.4705 12.9823 15.78 13.0635 16.0798C12.6547 16.1234 12.2424 16.1234 11.8335 16.0798C11.4435 16.0198 10.9635 15.2398 10.8335 14.9998C10.7692 14.871 10.6376 14.7895 10.4935 14.7895C10.3495 14.7895 10.2178 14.871 10.1535 14.9998C9.92353 15.3798 9.44353 16.0698 9.10353 16.1098C8.43353 16.1898 7.05353 16.1098 5.96353 16.1098C5.96353 16.1098 6.15353 15.1098 5.73353 14.7498C5.31353 14.3898 4.90353 13.9698 4.59353 13.6898L3.76353 12.7698C3.48353 12.4098 3.13353 11.6798 2.52353 10.7698C2.17353 10.2698 1.52353 9.67984 1.24353 9.18984C1.00845 8.79216 0.940151 8.31767 1.05353 7.86984C1.22333 7.2752 1.81419 6.9043 2.42353 7.00984C2.88703 7.04038 3.32544 7.2313 3.66353 7.54984C3.93124 7.78148 4.18189 8.03213 4.41353 8.29984C4.57353 8.48984 4.61353 8.57984 4.79353 8.80984C4.97353 9.03984 5.09353 9.26984 5.00353 8.92984" stroke="black" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.3555 13.0798V9.62802C12.3555 9.4214 12.1876 9.25391 11.9805 9.25391C11.7734 9.25391 11.6055 9.4214 11.6055 9.62802V13.0798C11.6055 13.2864 11.7734 13.4539 11.9805 13.4539C12.1876 13.4539 12.3555 13.2864 12.3555 13.0798Z" fill="black"/>
<path d="M10.3655 13.0796L10.3555 9.62605C10.3549 9.41993 10.1865 9.25331 9.97939 9.25391C9.77228 9.2545 9.60487 9.42208 9.60547 9.6282L9.61547 13.0818C9.61607 13.2879 9.78444 13.4545 9.99155 13.4539C10.1987 13.4533 10.3661 13.2857 10.3655 13.0796Z" fill="black"/>
<path d="M7.60938 9.62991L7.62938 13.0745C7.63059 13.2831 7.79947 13.4512 8.00657 13.45C8.21367 13.4488 8.38058 13.2787 8.37937 13.0701L8.35937 9.62549C8.35816 9.4169 8.18929 9.24879 7.98218 9.25001C7.77508 9.25123 7.60817 9.42131 7.60938 9.62991Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1,8 @@
<svg width="15" height="19" viewBox="0 0 15 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.05747 15.5237L12.1699 12.4692C12.6624 12.1035 12.8895 11.4794 12.7473 10.8827L11.6154 6.13304C11.4864 5.59169 11.0742 5.16222 10.5373 5.01207L6.60637 3.92049L6.2889 3.82351L5.95117 3.71215L5.41868 3.52427L5.05448 3.38923L4.50823 3.17899L3.80899 2.8991L3.04397 2.58152L0.695312 1.46484L1.31131 4.75424L1.37722 5.50451L1.42065 6.0882L1.4447 6.47587L1.47071 7.03993C1.47281 7.1008 1.47463 7.16095 1.47614 7.22024L1.48135 7.56472C1.48174 7.67545 1.48072 7.78174 1.4781 7.88258L1.39007 11.8061C1.37871 12.3635 1.67076 12.8822 2.15175 13.1621L6.37175 15.6181C6.90198 15.9266 7.56502 15.8895 8.05747 15.5237Z" fill="black"/>
<path d="M14.0286 14.2763C14.2617 14.5901 14.2192 15.0235 13.9439 15.2869L13.8703 15.349L10.1771 18.0921C9.83718 18.3445 9.35692 18.2736 9.10442 17.9337C8.87135 17.6199 8.91383 17.1865 9.18912 16.9231L9.26277 16.861L12.9559 14.118C13.2959 13.8654 13.7762 13.9363 14.0286 14.2763Z" fill="black"/>
<path d="M6.89838 8.4252C7.433 8.35384 7.98929 8.56725 8.33371 9.03096C8.83871 9.71082 8.69691 10.6714 8.01701 11.1764C7.33715 11.6814 6.37656 11.5396 5.87162 10.8597C5.52725 10.3961 5.48366 9.80203 5.70629 9.31089C5.65697 9.27113 5.61193 9.22449 5.57242 9.17131L2.94879 5.63894C2.93153 5.61568 2.9212 5.58801 2.91895 5.55913L2.86938 4.96079L2.81691 4.39698C2.80568 4.28142 2.92164 4.19525 3.02905 4.23944C3.11258 4.27381 3.19832 4.30888 3.28586 4.34446L3.82966 4.56235L4.11192 4.67278C4.13889 4.68325 4.16237 4.70113 4.17971 4.7244L6.80347 8.25695C6.8429 8.31007 6.87447 8.36664 6.89838 8.4252Z" fill="black"/>
<path d="M8.05747 15.5237L12.1699 12.4692C12.6624 12.1035 12.8895 11.4794 12.7473 10.8827L11.6154 6.13304C11.4864 5.59169 11.0742 5.16222 10.5373 5.01207L6.60637 3.92049L6.2889 3.82351L5.95117 3.71215L5.41868 3.52427L5.05448 3.38923L4.50823 3.17899L3.80899 2.8991L3.04397 2.58152L0.695312 1.46484L1.31131 4.75424L1.37722 5.50451L1.42065 6.0882L1.4447 6.47587L1.47071 7.03993C1.47281 7.1008 1.47463 7.16095 1.47614 7.22024L1.48135 7.56472C1.48174 7.67545 1.48072 7.78174 1.4781 7.88258L1.39007 11.8061C1.37871 12.3635 1.67076 12.8822 2.15175 13.1621L6.37175 15.6181C6.90198 15.9266 7.56502 15.8895 8.05747 15.5237Z" stroke="white"/>
<path d="M14.0286 14.2763C14.2617 14.5901 14.2192 15.0235 13.9439 15.2869L13.8703 15.349L10.1771 18.0921C9.83718 18.3445 9.35692 18.2736 9.10442 17.9337C8.87135 17.6199 8.91383 17.1865 9.18912 16.9231L9.26277 16.861L12.9559 14.118C13.2959 13.8654 13.7762 13.9363 14.0286 14.2763Z" stroke="white"/>
<path d="M6.89838 8.4252C7.433 8.35384 7.98929 8.56725 8.33371 9.03096C8.83871 9.71082 8.69691 10.6714 8.01701 11.1764C7.33715 11.6814 6.37656 11.5396 5.87162 10.8597C5.52725 10.3961 5.48366 9.80203 5.70629 9.31089C5.65697 9.27113 5.61193 9.22449 5.57242 9.17131L2.94879 5.63894C2.93153 5.61568 2.9212 5.58801 2.91895 5.55913L2.86938 4.96079L2.81691 4.39698C2.80568 4.28142 2.92164 4.19525 3.02905 4.23944C3.11258 4.27381 3.19832 4.30888 3.28586 4.34446L3.82966 4.56235L4.11192 4.67278C4.13889 4.68325 4.16237 4.70113 4.17971 4.7244L6.80347 8.25695C6.8429 8.31007 6.87447 8.36664 6.89838 8.4252Z" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,7 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.90366 12.8932C3.62366 12.5332 3.27366 11.8032 2.66366 10.8932C2.31366 10.3932 1.45366 9.44321 1.19366 8.95321C1.00623 8.65544 0.951847 8.29286 1.04366 7.95321C1.20062 7.30742 1.81322 6.87903 2.47366 6.95321C2.98446 7.05582 3.45388 7.30618 3.82366 7.67321C4.08184 7.91638 4.31933 8.18063 4.53366 8.46321C4.69366 8.66321 4.73366 8.74321 4.91366 8.97321C5.09366 9.20321 5.21366 9.43321 5.12366 9.09321C5.05366 8.59321 4.93366 7.75321 4.76366 7.00321C4.63366 6.43321 4.60366 6.34321 4.48366 5.91321C4.36366 5.48321 4.29366 5.12321 4.16366 4.63321C4.04483 4.15178 3.95137 3.66444 3.88366 3.17321C3.75761 2.54491 3.84932 1.89242 4.14366 1.32321C4.49305 0.994578 5.00559 0.907841 5.44366 1.10321C5.88426 1.42855 6.21276 1.88286 6.38366 2.40321C6.64573 3.0436 6.82062 3.71627 6.90366 4.40321C7.06366 5.40321 7.37366 6.86321 7.38366 7.16321C7.38366 6.79321 7.31366 6.01321 7.38366 5.66321C7.45301 5.29833 7.70662 4.99552 8.05366 4.86321C8.35147 4.77183 8.66651 4.75129 8.97366 4.80321C9.2837 4.86802 9.55832 5.04635 9.74366 5.30321C9.97534 5.8866 10.1039 6.50581 10.1237 7.13321C10.1504 6.5838 10.2445 6.03974 10.4037 5.51321C10.5708 5.27776 10.8148 5.108 11.0937 5.03321C11.4243 4.97276 11.7631 4.97276 12.0937 5.03321C12.3648 5.12384 12.6019 5.29472 12.7737 5.52321C12.9854 6.05355 13.1136 6.61355 13.1537 7.18321C13.1537 7.32321 13.2237 6.79321 13.4437 6.44321C13.558 6.10381 13.8447 5.85118 14.1958 5.78048C14.5469 5.70979 14.909 5.83178 15.1458 6.10048C15.3826 6.36919 15.458 6.74381 15.3437 7.08321C15.3437 7.73321 15.3437 7.70321 15.3437 8.14321C15.3437 8.58321 15.3437 8.97321 15.3437 9.34321C15.3072 9.92839 15.227 10.51 15.1037 11.0832C14.9296 11.5903 14.6874 12.0714 14.3837 12.5132C13.8981 13.0532 13.4969 13.6634 13.1937 14.3232C13.1184 14.651 13.0848 14.987 13.0937 15.3232C13.0927 15.6338 13.133 15.9432 13.2137 16.2432C12.8048 16.2864 12.3925 16.2864 11.9837 16.2432C11.5937 16.1832 11.1137 15.4032 10.9837 15.1632C10.9193 15.0343 10.7877 14.9529 10.6437 14.9529C10.4996 14.9529 10.368 15.0343 10.3037 15.1632C10.0837 15.5432 9.59366 16.2332 9.25366 16.2732C8.58366 16.3532 7.20366 16.2732 6.11366 16.2732C6.11366 16.2732 6.29366 15.2732 5.88366 14.9132C5.47366 14.5532 5.05366 14.1332 4.74366 13.8532L3.90366 12.8932Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.90366 12.8932C3.62366 12.5332 3.27366 11.8032 2.66366 10.8932C2.31366 10.3932 1.45366 9.44321 1.19366 8.95321C1.00623 8.65544 0.951847 8.29286 1.04366 7.95321C1.20062 7.30742 1.81322 6.87903 2.47366 6.95321C2.98446 7.05582 3.45388 7.30618 3.82366 7.67321C4.08184 7.91638 4.31933 8.18063 4.53366 8.46321C4.69366 8.66321 4.73366 8.74321 4.91366 8.97321C5.09366 9.20321 5.21366 9.43321 5.12366 9.09321C5.05366 8.59321 4.93366 7.75321 4.76366 7.00321C4.63366 6.43321 4.60366 6.34321 4.48366 5.91321C4.36366 5.48321 4.29366 5.12321 4.16366 4.63321C4.04483 4.15178 3.95137 3.66444 3.88366 3.17321C3.75761 2.54491 3.84932 1.89242 4.14366 1.32321C4.49305 0.994578 5.00559 0.907841 5.44366 1.10321C5.88426 1.42855 6.21276 1.88286 6.38366 2.40321C6.64573 3.0436 6.82062 3.71627 6.90366 4.40321C7.06366 5.40321 7.37366 6.86321 7.38366 7.16321C7.38366 6.79321 7.31366 6.01321 7.38366 5.66321C7.45301 5.29833 7.70662 4.99552 8.05366 4.86321C8.35147 4.77183 8.66651 4.75129 8.97366 4.80321C9.2837 4.86802 9.55832 5.04635 9.74366 5.30321C9.97534 5.8866 10.1039 6.50581 10.1237 7.13321C10.1504 6.5838 10.2445 6.03974 10.4037 5.51321C10.5708 5.27776 10.8148 5.108 11.0937 5.03321C11.4243 4.97276 11.7631 4.97276 12.0937 5.03321C12.3648 5.12384 12.6019 5.29472 12.7737 5.52321C12.9854 6.05355 13.1136 6.61355 13.1537 7.18321C13.1537 7.32321 13.2237 6.79321 13.4437 6.44321C13.558 6.10381 13.8447 5.85118 14.1958 5.78048C14.5469 5.70979 14.909 5.83178 15.1458 6.10048C15.3826 6.36919 15.458 6.74381 15.3437 7.08321C15.3437 7.73321 15.3437 7.70321 15.3437 8.14321C15.3437 8.58321 15.3437 8.97321 15.3437 9.34321C15.3072 9.92839 15.227 10.51 15.1037 11.0832C14.9296 11.5903 14.6874 12.0714 14.3837 12.5132C13.8981 13.0532 13.4969 13.6634 13.1937 14.3232C13.1184 14.651 13.0848 14.987 13.0937 15.3232C13.0927 15.6338 13.133 15.9432 13.2137 16.2432C12.8048 16.2864 12.3925 16.2864 11.9837 16.2432C11.5937 16.1832 11.1137 15.4032 10.9837 15.1632C10.9193 15.0343 10.7877 14.9529 10.6437 14.9529C10.4996 14.9529 10.368 15.0343 10.3037 15.1632C10.0837 15.5432 9.59366 16.2332 9.25366 16.2732C8.58366 16.3532 7.20366 16.2732 6.11366 16.2732C6.11366 16.2732 6.29366 15.2732 5.88366 14.9132C5.47366 14.5532 5.05366 14.1332 4.74366 13.8532L3.90366 12.8932Z" stroke="black" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.3828 13.4392V9.98739C12.3828 9.78078 12.2149 9.61328 12.0078 9.61328C11.8007 9.61328 11.6328 9.78078 11.6328 9.98739V13.4392C11.6328 13.6458 11.8007 13.8133 12.0078 13.8133C12.2149 13.8133 12.3828 13.6458 12.3828 13.4392Z" fill="black"/>
<path d="M10.4028 13.4379L10.3828 9.98435C10.3816 9.77823 10.2128 9.6121 10.0057 9.61329C9.79855 9.61448 9.63163 9.78253 9.63282 9.98865L9.65282 13.4422C9.65401 13.6483 9.82287 13.8145 10.03 13.8133C10.2371 13.8121 10.404 13.644 10.4028 13.4379Z" fill="black"/>
<path d="M7.63282 9.99227L7.65282 13.4387C7.65403 13.6468 7.8229 13.8145 8.03 13.8133C8.2371 13.8121 8.40401 13.6424 8.40281 13.4343L8.38281 9.98788C8.3816 9.77978 8.21273 9.61207 8.00563 9.61329C7.79852 9.6145 7.63161 9.78418 7.63282 9.99227Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

1
app/src/assets/react.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

View File

@@ -0,0 +1,290 @@
import React, { useState, useRef, useEffect, act } from "react";
import img from "../../assets/image/image.png";
import { useNavigate } from "react-router-dom";
import { getUserData } from "../../functions/getUserData";
import { useLoadingProgress, useProjectName, useSocketStore } from "../../store/builder/store";
import { viewProject } from "../../services/dashboard/viewProject";
import OuterClick from "../../utils/outerClick";
import { KebabIcon } from "../icons/ExportCommonIcons";
import { getAllProjects } from "../../services/dashboard/getAllProjects";
interface DashBoardCardProps {
projectName: string;
thumbnail: any;
projectId: string;
createdAt?: string;
isViewed?: string;
createdBy?: { _id: string, userName: string };
handleDeleteProject?: (projectId: string) => Promise<void>;
handleTrashDeleteProject?: (projectId: string) => Promise<void>;
handleRestoreProject?: (projectId: string) => Promise<void>;
handleDuplicateWorkspaceProject?: (
projectId: string,
projectName: string,
thumbnail: string,
userId?: string
) => Promise<void>;
handleDuplicateRecentProject?: (
projectId: string,
projectName: string,
thumbnail: string
) => Promise<void>;
active?: string;
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
setRecentDuplicateData?: React.Dispatch<React.SetStateAction<Object>>;
setProjectDuplicateData?: React.Dispatch<React.SetStateAction<Object>>;
setActiveFolder?: React.Dispatch<React.SetStateAction<string>>;
}
type RelativeTimeFormatUnit = any;
const DashboardCard: React.FC<DashBoardCardProps> = ({
projectName,
thumbnail,
projectId,
active,
handleDeleteProject,
handleRestoreProject,
handleTrashDeleteProject,
handleDuplicateWorkspaceProject,
handleDuplicateRecentProject,
createdAt,
createdBy,
setRecentDuplicateData,
setProjectDuplicateData,
setActiveFolder
}) => {
const navigate = useNavigate();
const { setProjectName } = useProjectName();
const { userId, organization, userName } = getUserData();
const [isKebabOpen, setIsKebabOpen] = useState(false);
const [renameValue, setRenameValue] = useState(projectName);
const [isRenaming, setIsRenaming] = useState(false);
const { projectSocket } = useSocketStore();
const { setLoadingProgress } = useLoadingProgress();
const kebabRef = useRef<HTMLDivElement>(null);
const navigateToProject = async (e: any) => {
console.log('active: ', active);
if (active && active == "trash") return;
try {
const viewProjects = await viewProject(organization, projectId, userId)
console.log('viewProjects: ', viewProjects);
console.log('projectName: ', projectName);
setLoadingProgress(1)
setProjectName(projectName);
navigate(`/${projectId}`);
} catch {
}
};
const handleOptionClick = async (option: string) => {
switch (option) {
case "delete":
if (handleDeleteProject) {
handleDeleteProject(projectId);
} else if (handleTrashDeleteProject) {
handleTrashDeleteProject(projectId);
}
break;
case "restore":
if (handleRestoreProject) {
await handleRestoreProject(projectId);
}
break;
case "open in new tab":
try {
if (active === "shared" && createdBy) {
console.log("ihreq");
const newTab = await viewProject(organization, projectId, createdBy?._id);
console.log('newTab: ', newTab);
} else {
const newTab = await viewProject(organization, projectId, userId);
console.log('newTab: ', newTab);
setProjectName(projectName);
setIsKebabOpen(false);
}
} catch (error) {
}
window.open(`/${projectId}`, "_blank");
break;
case "rename":
setIsRenaming(true);
break;
case "duplicate":
if (handleDuplicateWorkspaceProject) {
setProjectDuplicateData &&
setProjectDuplicateData({
projectId,
projectName,
thumbnail,
});
await handleDuplicateWorkspaceProject(projectId, projectName, thumbnail, userId);
if (active === "shared" && setActiveFolder) {
setActiveFolder("myProjects")
}
} else if (handleDuplicateRecentProject) {
setRecentDuplicateData &&
setRecentDuplicateData({
projectId,
projectName,
thumbnail,
userId
});
await handleDuplicateRecentProject(projectId, projectName, thumbnail);
}
break;
default:
break;
}
setIsKebabOpen(false);
};
OuterClick({
contextClassName: ["kebab-wrapper", "kebab-options-wrapper"],
setMenuVisible: () => setIsKebabOpen(false),
});
const handleProjectName = async (projectName: string) => {
setRenameValue(projectName);
if (!projectId) return;
try {
const projects = await getAllProjects(userId, organization);
if (!projects || !projects.Projects) return;
let projectUuid = projects.Projects.find(
(val: any) => val.projectUuid === projectId || val._id === projectId
);
const updateProjects = {
projectId: projectUuid,
organization,
userId,
projectName,
thumbnail: undefined,
};
if (projectSocket) {
projectSocket.emit("v1:project:update", updateProjects);
}
} catch (error) { }
};
function getRelativeTime(dateString: string): string {
const date = new Date(dateString);
const now = new Date();
const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
const intervals: Record<RelativeTimeFormatUnit, number> = {
year: 31536000,
month: 2592000,
week: 604800,
day: 86400,
hour: 3600,
minute: 60,
second: 1,
};
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
for (const key in intervals) {
const unit = key as RelativeTimeFormatUnit;
const diff = Math.floor(diffInSeconds / intervals[unit]);
if (diff >= 1) {
return rtf.format(-diff, unit);
}
}
return "just now";
}
const kebabOptionsMap: Record<string, string[]> = {
default: ["rename", "delete", "duplicate", "open in new tab"],
trash: ["restore", "delete"],
shared: ["duplicate", "open in new tab"],
};
const getOptions = () => {
if (active === "trash") return kebabOptionsMap.trash;
if (active === "shared") return kebabOptionsMap.shared;
if (createdBy && createdBy?._id !== userId) return kebabOptionsMap.shared;
return kebabOptionsMap.default;
};
return (
<button
className="dashboard-card-container"
onClick={navigateToProject}
title={projectName}
onMouseLeave={() => setIsKebabOpen(false)}
>
<div className="dashboard-card-wrapper">
<div className="preview-container">
{thumbnail ? <img src={thumbnail} alt="" /> : <img src={img} alt="" />}
</div>
<div className="project-details-container" onClick={(e) => { e.stopPropagation() }}>
<div className="project-details">
{isRenaming ? (
<input
value={renameValue}
onChange={(e) => {
e.stopPropagation();
handleProjectName(e.target.value);
}}
onBlur={() => {
setIsRenaming(false);
setProjectName(renameValue);
}}
onKeyDown={(e) => {
if (e.key === "Enter") {
setProjectName(renameValue);
setIsRenaming(false);
}
}}
autoFocus
/>
) : (
<span>{renameValue}</span>
)}
{createdAt && (
<div className="project-data">
{active && active == "trash" ? `Trashed by you` : `Edited `}{" "}
{getRelativeTime(createdAt)}
</div>
)}
</div>
<div className="users-list-container" ref={kebabRef}>
<div className="user-profile">
{(!createdBy) ? userName ? userName?.charAt(0).toUpperCase() : "A" : createdBy?.userName?.charAt(0).toUpperCase()}
</div>
<button
className="kebab-wrapper"
onClick={(e) => {
e.stopPropagation();
setIsKebabOpen((prev) => !prev);
}}
>
<KebabIcon />
</button>
</div>
</div>
</div>
{isKebabOpen && (
<div className="kebab-options-wrapper">
{getOptions().map((option) => (
<button
key={option}
className="option"
onClick={(e) => {
e.stopPropagation();
handleOptionClick(option);
}}
>
{option}
</button>
))}
</div>
)}
</button>
);
};
export default DashboardCard;

View File

@@ -0,0 +1,166 @@
import React, { useEffect, useState } from "react";
import DashboardCard from "./DashboardCard";
import DashboardNavBar from "./DashboardNavBar";
import MarketPlaceBanner from "./MarketPlaceBanner";
import { getUserData } from "../../functions/getUserData";
import { useSocketStore } from "../../store/builder/store";
import { recentlyViewed } from "../../services/dashboard/recentlyViewed";
import { searchProject } from "../../services/dashboard/searchProjects";
import { deleteProject } from "../../services/dashboard/deleteProject";
import ProjectSocketRes from "./socket/projectSocketRes.dev";
interface Project {
_id: string;
projectName: string;
thumbnail: string;
createdBy: { _id: string, userName: string };
projectUuid?: string;
createdAt: string;
isViewed?: string
}
interface RecentProjectsData {
[key: string]: Project[];
}
const DashboardHome: React.FC = () => {
const [recentProjects, setRecentProjects] = useState<RecentProjectsData>({});
const [isSearchActive, setIsSearchActive] = useState<boolean>(false);
const { userId, organization } = getUserData();
const { projectSocket } = useSocketStore();
const [recentDuplicateData, setRecentDuplicateData] = useState<Object>({});
const fetchRecentProjects = async () => {
try {
const projects = await recentlyViewed(organization, userId);
if (JSON.stringify(projects) !== JSON.stringify(recentProjects)) {
setRecentProjects(projects);
}
} catch (error) {
console.error("Error fetching recent projects:", error);
}
};
const handleRecentProjectSearch = async (inputValue: string) => {
if (!inputValue.trim()) {
setIsSearchActive(false);
return;
}
const filterRecentProcess = await searchProject(
organization,
userId,
inputValue
);
setIsSearchActive(true);
setRecentProjects(filterRecentProcess.message ? {} : filterRecentProcess);
};
const handleDeleteProject = async (projectId: any) => {
try {
//API for delete project
// const deletedProject = await deleteProject(
// projectId,
// userId,
// organization
// );
// console.log('deletedProject: ', deletedProject);
//socket for delete Project
const deleteProject = {
projectId,
organization,
userId,
};
if (projectSocket) {
projectSocket.emit("v1:project:delete", deleteProject);
}
setRecentProjects((prevDiscardedProjects: RecentProjectsData) => {
if (!Array.isArray(prevDiscardedProjects?.RecentlyViewed)) {
return prevDiscardedProjects;
}
const updatedProjectDatas = prevDiscardedProjects.RecentlyViewed.filter(
(project) => project._id !== projectId
);
return {
...prevDiscardedProjects,
RecentlyViewed: updatedProjectDatas,
};
});
setIsSearchActive(false);
} catch (error) {
console.error("Error deleting project:", error);
}
};
const handleDuplicateRecentProject = async (
projectId: string,
projectName: string,
thumbnail: string
) => {
const duplicateRecentProjectData = {
userId,
thumbnail,
organization,
projectUuid: projectId,
projectName,
};
projectSocket.emit("v1:project:Duplicate", duplicateRecentProjectData);
};
const renderProjects = () => {
const projectList = recentProjects[Object.keys(recentProjects)[0]];
if (!projectList?.length) {
return <div className="empty-state">No recent projects found</div>;
}
return (
projectList &&
projectList.map((project) => (
<DashboardCard
key={project._id}
projectName={project.projectName}
thumbnail={project.thumbnail}
projectId={project._id}
createdBy={project.createdBy}
createdAt={project.createdAt}
handleDeleteProject={handleDeleteProject}
handleDuplicateRecentProject={handleDuplicateRecentProject}
setRecentDuplicateData={setRecentDuplicateData}
/>
))
);
};
useEffect(() => {
if (!isSearchActive) {
fetchRecentProjects();
}
}, [isSearchActive]);
return (
<div className="dashboard-home-container">
<DashboardNavBar
page="home"
handleRecentProjectSearch={handleRecentProjectSearch}
/>
<MarketPlaceBanner />
<div className="dashboard-container">
<h2 className="section-header">Recents</h2>
<div className="cards-container">{renderProjects()}</div>
</div>
{recentDuplicateData && Object.keys(recentDuplicateData).length > 0 && (
<ProjectSocketRes
setIsSearchActive={setIsSearchActive}
setRecentProjects={setRecentProjects}
/>
)}
</div>
);
};
export default DashboardHome;

View File

@@ -0,0 +1,43 @@
import React from "react";
import Search from "../ui/inputs/Search";
import { CartIcon } from "../icons/ExportModuleIcons";
interface DashboardNavBarProps {
page: React.ReactNode;
handleProjectsSearch?: (inputValue: string) => Promise<void>;
handleTrashSearch?: (inputValue: string) => Promise<void>;
handleRecentProjectSearch?: (inputValue: string) => Promise<void>;
}
const DashboardNavBar: React.FC<DashboardNavBarProps> = ({
page,
handleProjectsSearch,
handleTrashSearch,
handleRecentProjectSearch,
}) => {
const handleSearch = async (inputValue: string) => {
try {
if (handleProjectsSearch) {
await handleProjectsSearch(inputValue);
} else if (handleTrashSearch) {
await handleTrashSearch(inputValue);
} else if (handleRecentProjectSearch) {
await handleRecentProjectSearch(inputValue);
}
} catch (error) {
console.error("Search failed:", error);
}
};
return (
<div className="dashboard-navbar-container">
<div className="title">{page}</div>
<div className="market-place-button">
<CartIcon isActive /> Market Place
</div>
<Search onChange={handleSearch} />
</div>
);
};
export default DashboardNavBar;

View File

@@ -0,0 +1,217 @@
import React, { useEffect, useState } from "react";
import DashboardNavBar from "./DashboardNavBar";
import DashboardCard from "./DashboardCard";
import { getUserData } from "../../functions/getUserData";
import { useSocketStore } from "../../store/builder/store";
import { getAllProjects } from "../../services/dashboard/getAllProjects";
import { searchProject } from "../../services/dashboard/searchProjects";
import { deleteProject } from "../../services/dashboard/deleteProject";
import ProjectSocketRes from "./socket/projectSocketRes.dev";
import { sharedWithMeProjects } from "../../services/dashboard/sharedWithMeProject";
import { duplicateProject } from "../../services/dashboard/duplicateProject";
interface Project {
_id: string;
projectName: string;
thumbnail: string;
createdBy: string;
projectUuid?: string;
createdAt: string;
}
interface WorkspaceProjects {
[key: string]: Project[];
}
const DashboardProjects: React.FC = () => {
const [workspaceProjects, setWorkspaceProjects] = useState<WorkspaceProjects>(
{}
);
const [sharedwithMeProject, setSharedWithMeProjects] = useState<any>([])
const [projectDuplicateData, setProjectDuplicateData] = useState<Object>({});
const [isSearchActive, setIsSearchActive] = useState<boolean>(false);
const [activeFolder, setActiveFolder] = useState<string>("myProjects");
const { projectSocket } = useSocketStore();
const { userId, organization } = getUserData();
const handleProjectsSearch = async (inputValue: string) => {
if (!inputValue.trim()) {
setIsSearchActive(false);
return;
}
if (!setWorkspaceProjects || !setIsSearchActive) return;
const searchedProject = await searchProject(organization, userId, inputValue);
setIsSearchActive(true);
setWorkspaceProjects(searchedProject.message ? {} : searchedProject);
};
const fetchAllProjects = async () => {
try {
const projects = await getAllProjects(userId, organization);
if (!projects || !projects.Projects) return;
if (JSON.stringify(projects) !== JSON.stringify(workspaceProjects)) {
setWorkspaceProjects(projects);
}
} catch (error) {
console.error("Error fetching projects:", error);
}
};
const handleDeleteProject = async (projectId: any) => {
try {
// const deletedProject = await deleteProject(
// projectId,
// userId,
// organization
// );
// console.log('deletedProject: ', deletedProject);
const deleteProjects = {
projectId,
organization,
userId,
};
//socket for deleting the project
if (projectSocket) {
projectSocket.emit("v1:project:delete", deleteProjects);
} else {
console.error("Socket is not connected.");
}
setWorkspaceProjects((prevDiscardedProjects: WorkspaceProjects) => {
if (!Array.isArray(prevDiscardedProjects?.Projects)) {
return prevDiscardedProjects;
}
const updatedProjectDatas = prevDiscardedProjects.Projects.filter(
(project) => project._id !== projectId
);
return {
...prevDiscardedProjects,
Projects: updatedProjectDatas,
};
});
setIsSearchActive(false);
} catch (error) {
console.error("Error deleting project:", error);
}
};
const handleDuplicateWorkspaceProject = async (
projectId: string,
projectName: string,
thumbnail: string,
) => {
const duplicateProjectData = {
userId,
thumbnail,
organization,
projectUuid: projectId,
projectName,
};
projectSocket.emit("v1:project:Duplicate", duplicateProjectData);
};
const renderProjects = () => {
if (activeFolder !== "myProjects") return null;
const projectList = workspaceProjects[Object.keys(workspaceProjects)[0]];
if (!projectList?.length) {
return <div className="empty-state">No projects found</div>;
}
return projectList.map((project) => (
<DashboardCard
key={project._id}
projectName={project.projectName}
thumbnail={project.thumbnail}
projectId={project._id}
createdAt={project.createdAt}
handleDeleteProject={handleDeleteProject}
setIsSearchActive={setIsSearchActive}
handleDuplicateWorkspaceProject={handleDuplicateWorkspaceProject}
setProjectDuplicateData={setProjectDuplicateData}
/>
));
};
const renderSharedProjects = () => {
return sharedwithMeProject?.map((project: any) => (
<DashboardCard
key={project._id}
projectName={project.projectName}
thumbnail={project.thumbnail}
projectId={project._id}
createdAt={project.createdAt}
setIsSearchActive={setIsSearchActive}
active="shared"
createdBy={project.createdBy}
setProjectDuplicateData={setProjectDuplicateData}
handleDuplicateWorkspaceProject={handleDuplicateWorkspaceProject}
setActiveFolder={setActiveFolder}
/>
));
};
const sharedProject = async () => {
try {
const sharedWithMe = await sharedWithMeProjects();
setSharedWithMeProjects(sharedWithMe)
} catch {
}
}
useEffect(() => {
if (!isSearchActive) {
fetchAllProjects();
}
}, [isSearchActive]);
useEffect(() => {
if (activeFolder === "shared") {
sharedProject()
}
}, [activeFolder])
return (
<div className="dashboard-home-container">
<DashboardNavBar
page="projects"
handleProjectsSearch={handleProjectsSearch}
/>
<div className="dashboard-container" style={{ height: "calc(100% - 87px)" }}>
<div className="header-wrapper" style={{ display: "flex", gap: "7px" }}>
<button
className={`header ${activeFolder === "myProjects" && "active"}`}
onClick={() => setActiveFolder("myProjects")}
>
My Projects
</button>
<button
className={`header ${activeFolder === "shared" && "active"}`}
onClick={() => setActiveFolder("shared")}
>
Shared with me
</button>
</div>
<div className="cards-container">{activeFolder == "myProjects" ? renderProjects() : renderSharedProjects()}</div>
{projectDuplicateData && Object.keys(projectDuplicateData).length > 0 && (
<ProjectSocketRes
setIsSearchActive={setIsSearchActive}
setWorkspaceProjects={setWorkspaceProjects}
/>
)}
</div>
</div>
);
};
export default DashboardProjects;

View File

@@ -0,0 +1,157 @@
import React, { useEffect, useState } from "react";
import DashboardCard from "./DashboardCard";
import DashboardNavBar from "./DashboardNavBar";
import { getUserData } from "../../functions/getUserData";
import { trashSearchProject } from "../../services/dashboard/trashSearchProject";
import { restoreTrash } from "../../services/dashboard/restoreTrash";
import { getTrash } from "../../services/dashboard/getTrash";
import { deleteTrash } from "../../services/dashboard/deleteTrash";
import { useSocketStore } from "../../store/builder/store";
interface Project {
_id: string;
projectName: string;
thumbnail: string;
createdBy: string;
projectUuid?: string;
DeletedAt: string;
}
interface DiscardedProjects {
[key: string]: Project[];
}
const DashboardTrash: React.FC = () => {
const [discardedProjects, setDiscardedProjects] = useState<DiscardedProjects>({});
const [isSearchActive, setIsSearchActive] = useState(false);
const { userId, organization } = getUserData();
const { projectSocket } = useSocketStore();
const fetchTrashProjects = async () => {
try {
const projects = await getTrash(organization);
if (JSON.stringify(projects) !== JSON.stringify(discardedProjects)) {
setDiscardedProjects(projects);
}
} catch (error) {
console.error("Error fetching trash projects:", error);
}
};
const handleTrashSearch = async (inputValue: string) => {
if (!inputValue.trim()) {
setIsSearchActive(false);
return;
}
if (!setDiscardedProjects || !setIsSearchActive) return;
const filterTrashedProcess = await trashSearchProject(
organization,
userId,
inputValue
);
setIsSearchActive(true);
setDiscardedProjects(
filterTrashedProcess.message ? {} : filterTrashedProcess
);
};
const handleRestoreProject = async (projectId: any) => {
try {
const restoreProject = await restoreTrash(organization, projectId);
// console.log('restoreProject: ', restoreProject);
setDiscardedProjects((prevDiscardedProjects: DiscardedProjects) => {
// Check if TrashDatas exists and is an array
if (!Array.isArray(prevDiscardedProjects?.TrashDatas)) {
console.error("TrashDatas is not an array", prevDiscardedProjects);
return prevDiscardedProjects;
}
const updatedTrashDatas = prevDiscardedProjects.TrashDatas.filter(
(project) => project._id !== projectId
);
return {
...prevDiscardedProjects,
TrashDatas: updatedTrashDatas,
};
});
setIsSearchActive(false);
} catch (error) {
console.error("Error deleting project:", error);
}
};
const handleTrashDeleteProject = async (projectId: any) => {
try {
// const deletedProject = await deleteTrash(
// organization, projectId
// );
const deleteProjectTrash = {
projectId,
organization,
userId,
};
if (projectSocket) {
projectSocket.emit("v1:trash:delete", deleteProjectTrash);
}
setDiscardedProjects((prevDiscardedProjects: DiscardedProjects) => {
if (!Array.isArray(prevDiscardedProjects?.TrashDatas)) {
return prevDiscardedProjects;
}
const updatedProjectDatas = prevDiscardedProjects.TrashDatas.filter(
(project) => project._id !== projectId
);
// console.log('updatedProjectDatas: ', updatedProjectDatas);
return {
...prevDiscardedProjects,
TrashDatas: updatedProjectDatas,
};
});
setIsSearchActive(false);
} catch (error) {
console.error("Error deleting project:", error);
}
};
const renderTrashProjects = () => {
const projectList = discardedProjects[Object.keys(discardedProjects)[0]];
if (!projectList?.length) {
return <div className="empty-state">No deleted projects found</div>;
}
return projectList.map((project) => (
<DashboardCard
key={project._id}
projectName={project.projectName}
thumbnail={project.thumbnail}
projectId={project._id}
handleRestoreProject={handleRestoreProject}
handleTrashDeleteProject={handleTrashDeleteProject}
active={"trash"}
createdAt={project.DeletedAt}
/>
));
};
useEffect(() => {
if (!isSearchActive) {
fetchTrashProjects();
}
}, [isSearchActive]);
return (
<div className="dashboard-home-container">
<DashboardNavBar page="trash" handleTrashSearch={handleTrashSearch} />
<div className="dashboard-container" style={{ height: "calc(100% - 87px)" }}>
<div className="header" style={{ display: "flex", gap: "7px" }}></div>
<div className="cards-container">{renderTrashProjects()}</div>
</div>
</div>
);
};
export default DashboardTrash;

View File

@@ -0,0 +1,62 @@
import React, { useEffect, useState } from 'react';
import DashboardNavBar from './DashboardNavBar';
import DashboardCard from './DashboardCard';
import { projectTutorial } from '../../services/dashboard/projectTutorial';
interface Project {
_id: string;
projectName: string;
thumbnail: string;
createdBy: string;
projectUuid?: string;
}
interface DiscardedProjects {
[key: string]: Project[];
}
const DashboardTutorial = () => {
const [tutorialProject, setTutorialProject] = useState<DiscardedProjects>({})
const handleIcon = async () => {
try {
let tutorial = await projectTutorial()
setTutorialProject(tutorial)
} catch {
}
}
useEffect(() => {
handleIcon()
}, [])
const renderTrashProjects = () => {
const projectList = tutorialProject[Object.keys(tutorialProject)[0]];
if (!projectList?.length) {
return <div className="empty-state">No deleted projects found</div>;
}
return projectList.map((tutorials: any) => (
<DashboardCard
key={tutorials._id}
projectName={tutorials.projectName}
thumbnail={tutorials.thumbnail}
projectId={tutorials._id}
/>
));
};
return (
<div className="dashboard-home-container">
<DashboardNavBar
page="tutorial"
/>
<div className="dashboard-container" style={{ height: "calc(100% - 87px)" }}>
<div className="header" style={{ display: 'flex', gap: '7px' }}></div>
<div className="cards-container">
{renderTrashProjects()}
</div>
</div>
</div>
);
}
export default DashboardTutorial;

View File

@@ -0,0 +1,44 @@
import React from "react";
import banner from "../../assets/image/banner.png";
const MarketPlaceBanner = () => {
return (
<div className="market-place-banner-container">
{/* market place banner */}
<img src={banner} alt="" />
<div className="hero-text">
NEW
<br /> FALL
<br /> COLLECTION
</div>
<div className="context">Unlock Creativity with Premium 3D Assets!</div>
<div className="arrow-context">
<svg
width="169"
height="120"
viewBox="0 0 169 120"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M167.189 2C154.638 36.335 104.466 106.204 4.18872 111"
stroke="white"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M10.662 118.326L1.59439 111.524L9.47334 103.374"
stroke="white"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="explore-button">Explore Now</div>
</div>
);
};
export default MarketPlaceBanner;

View File

@@ -0,0 +1,182 @@
import React from "react";
import {
DocumentationIcon,
HelpIcon,
HomeIcon,
LogoutIcon,
NotificationIcon,
ProjectsIcon,
TutorialsIcon,
} from "../icons/DashboardIcon";
import { useNavigate } from "react-router-dom";
import darkThemeImage from "../../assets/image/darkThemeProject.png";
import lightThemeImage from "../../assets/image/lightThemeProject.png";
import { SettingsIcon, TrashIcon } from "../icons/ExportCommonIcons";
import { getUserData } from "../../functions/getUserData";
import { useLoadingProgress, useSocketStore } from "../../store/builder/store";
import { createProject } from "../../services/dashboard/createProject";
interface SidePannelProps {
setActiveTab: React.Dispatch<React.SetStateAction<string>>;
activeTab: string;
}
const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
const { email, userName, userId, organization } = getUserData();
const navigate = useNavigate();
const { setLoadingProgress } = useLoadingProgress();
const { projectSocket } = useSocketStore();
const savedTheme = localStorage.getItem("theme") ?? "light";
function generateProjectId() {
const randomBytes = new Uint8Array(12);
crypto.getRandomValues(randomBytes);
return Array.from(randomBytes, (byte) =>
byte.toString(16).padStart(2, "0")
).join("");
}
const handleCreateNewProject = async () => {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken")
console.log('refreshToken: ', refreshToken);
try {
const projectId = generateProjectId();
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
//API for creating new Project
// const project = await createProject(
// projectId,
// userId,
// savedTheme === "dark" ? darkThemeImage : lightThemeImage,
// organization
// );
const addProject = {
userId,
thumbnail: savedTheme === "dark" ? darkThemeImage : lightThemeImage,
organization: organization,
projectUuid: projectId,
};
console.log('projectSocket: ', projectSocket);
if (projectSocket) {
const handleResponse = (data: any) => {
if (data.message === "Project created successfully") {
setLoadingProgress(1)
navigate(`/${data.data.projectId}`);
}
projectSocket.off("v1-project:response:add", handleResponse); // Clean up
};
projectSocket.on("v1-project:response:add", handleResponse);
projectSocket.emit("v1:project:add", addProject);
} else {
console.error("Socket is not connected.");
}
} catch (error) {
console.error("Error creating project:", error);
}
};
return (
<div className="side-pannel-container">
<div className="side-pannel-header">
<div className="user-container">
<div className="user-profile">
{userName?.charAt(0).toUpperCase()}
</div>
<div className="user-name">
{userName
? userName.charAt(0).toUpperCase() + userName.slice(1).toLowerCase()
: "Anonymous"}
</div>
</div>
<div className="notifications-container">
<NotificationIcon />
</div>
</div>
<div
className="new-project-button"
style={{ cursor: "pointer" }}
onClick={handleCreateNewProject}
>
+ New project
</div>
<div className="side-bar-content-container">
<div className="side-bar-options-container">
<div
className={
activeTab === "Home" ? "option-list active" : "option-list"
}
onClick={() => setActiveTab("Home")}
>
<HomeIcon />
Home
</div>
<div
className={
activeTab === "Projects" ? "option-list active" : "option-list"
}
title="Projects"
onClick={() => setActiveTab("Projects")}
>
<ProjectsIcon />
Projects
</div>
<div
className={
activeTab === "Trash" ? "option-list active" : "option-list"
}
title="Trash"
onClick={() => setActiveTab("Trash")}
>
<TrashIcon />
Trash
</div>
<div
className={
activeTab === "Tutorials" ? "option-list active" : "option-list"
}
title="coming soon"
onClick={() => setActiveTab("Tutorials")}
>
<TutorialsIcon />
Tutorials
</div>
<div
className={
activeTab === "Documentation"
? "option-list active"
: "option-list"
}
title="coming soon"
onClick={() => setActiveTab("Documentation")}
>
<DocumentationIcon />
Documentation
</div>
</div>
<div className="side-bar-options-container" title="coming soon">
<div className="option-list">
<SettingsIcon />
Settings
</div>
<div className="option-list" style={{ cursor: "pointer" }} onClick={() => {
localStorage.clear();
navigate("/");
}}>
<LogoutIcon />
Log out
</div>
<div className="option-list">
<HelpIcon />
Help & Feedback
</div>
</div>
</div>
</div>
);
};
export default SidePannel;

View File

@@ -0,0 +1,101 @@
import React, { useEffect } from 'react';
import { useSocketStore } from '../../../store/builder/store';
import { getUserData } from '../../../functions/getUserData';
import { getAllProjects } from '../../../services/dashboard/getAllProjects';
import { recentlyViewed } from '../../../services/dashboard/recentlyViewed';
interface Project {
_id: string;
projectName: string;
thumbnail: string;
createdBy: string;
projectUuid?: string;
createdAt: string;
isViewed?: string
}
interface RecentProject {
_id: string;
projectName: string;
thumbnail: string;
createdBy: { _id: string, userName: string };
projectUuid?: string;
createdAt: string;
isViewed?: string
}
interface RecentProjectData {
[key: string]: RecentProject[];
}
interface ProjectsData {
[key: string]: Project[];
}
interface ProjectSocketResProps {
setRecentProjects?: React.Dispatch<React.SetStateAction<RecentProjectData>>;
setWorkspaceProjects?: React.Dispatch<React.SetStateAction<ProjectsData>>;
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
}
const ProjectSocketRes = ({
setRecentProjects,
setWorkspaceProjects,
setIsSearchActive,
}: ProjectSocketResProps) => {
const { projectSocket } = useSocketStore();
const { userId, organization } = getUserData();
useEffect(() => {
if (!projectSocket) return;
const handleAdd = (data: any) => {
// console.log('Add:', data);
};
const handleDelete = (data: any) => {
// console.log('Delete:', data);
};
const handleUpdate = (data: any) => {
// console.log('Update:', data);
};
const handleTrashDelete = (data: any) => {
// console.log('Trash Delete:', data);
};
const handleDuplicate = async (data: any) => {
console.log("Project duplicate response:", data);
if (data?.message === "Project Duplicated successfully") {
if (setWorkspaceProjects) {
const allProjects = await getAllProjects(userId, organization);
// console.log('allProjects: ', allProjects);
setWorkspaceProjects(allProjects);
} else if (setRecentProjects) {
const recentProjects = await recentlyViewed(organization, userId);
setRecentProjects && setRecentProjects(recentProjects);
}
setIsSearchActive && setIsSearchActive(false);
} else {
console.warn("Duplication failed or unexpected response.");
}
};
projectSocket.on("v1-project:response:add", handleAdd);
projectSocket.on("v1-project:response:delete", handleDelete);
projectSocket.on("v1-project:response:update", handleUpdate);
projectSocket.on("v1-project:response:Duplicate", handleDuplicate);
projectSocket.on("v1:trash:response:delete", handleTrashDelete);
return () => {
projectSocket.off("v1-project:response:add", handleAdd);
projectSocket.off("v1-project:response:delete", handleDelete);
projectSocket.off("v1-project:response:update", handleUpdate);
projectSocket.off("v1-project:response:Duplicate", handleDuplicate);
projectSocket.off("v1:trash:response:delete", handleTrashDelete);
};
}, [projectSocket, userId, organization]);
return null;
};
export default ProjectSocketRes;

View File

@@ -0,0 +1,117 @@
import React, { useEffect } from "react";
import { HelpIcon } from "../icons/DashboardIcon";
import { useLogger } from "../ui/log/LoggerContext";
import { GetLogIcon } from "./getLogIcons";
import {
CurserLeftIcon,
CurserMiddleIcon,
CurserRightIcon,
} from "../icons/LogIcons";
import ShortcutHelper from "./shortcutHelper";
import useVersionHistoryVisibleStore, {
useShortcutStore,
} from "../../store/builder/store";
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
import useModuleStore, { useSubModuleStore } from "../../store/useModuleStore";
import { useVersionContext } from "../../modules/builder/version/versionContext";
import { mouseActionHelper } from "../../utils/mouseUtils/mouseHelper";
import { useMouseNoteStore } from "../../store/useUIToggleStore";
const Footer: React.FC = () => {
const { logs, setIsLogListVisible } = useLogger();
const lastLog = logs.length > 0 ? logs[logs.length - 1] : null;
const { setActiveModule } = useModuleStore();
const { setSubModule } = useSubModuleStore();
const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
const { isPlaying } = usePlayButtonStore();
const { showShortcuts, setShowShortcuts } = useShortcutStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { Leftnote, Middlenote, Rightnote } = useMouseNoteStore();
const mouseButtons = [
{
icon: <CurserLeftIcon />,
label: Leftnote !== "" ? Leftnote : "Pan",
mouse: "left",
},
{
icon: <CurserMiddleIcon />,
label: Middlenote !== "" ? Middlenote : "Scroll Zoom",
mouse: "middle",
},
{
icon: <CurserRightIcon />,
label: Rightnote !== "" ? Rightnote : "Orbit / Cancel action",
mouse: "right",
},
];
useEffect(() => {
const cleanup = mouseActionHelper();
return () => cleanup();
}, []);
return (
<div className="footer-container">
<div className="footer-wrapper">
<div className="selection-wrapper">
{mouseButtons.map(({ icon, label, mouse }) => (
<div className="selector-wrapper" key={mouse}>
<div className="icon">{icon}</div>
<div className="selector">{label}</div>
</div>
))}
</div>
<div className="logs-wrapper">
<div className="bg-dummy left-top"></div>
<div className="bg-dummy right-bottom"></div>
<div className="log-container">
<button
id="log-details-buttton"
className={`logs-detail ${lastLog ? lastLog.type : ""}`}
onClick={() => setIsLogListVisible(true)}
>
{lastLog ? (
<>
<span className="log-icon">{GetLogIcon(lastLog.type)}</span>
<span className="log-message">{lastLog.message}</span>
</>
) : (
"There are no logs to display at the moment."
)}
</button>
</div>
<div
className="version"
onClick={() => {
setVersionHistoryVisible(true);
setSubModule("properties");
setActiveModule("builder");
}}
>
{selectedVersion?.version ?? "v 0.0.0"}
<div className="icon">
<HelpIcon />
</div>
</div>
</div>
</div>
{!isPlaying && (
<div
className={`shortcut-helper-overlay ${
showShortcuts ? "visible" : ""
}`}
>
<ShortcutHelper setShowShortcuts={setShowShortcuts} />
</div>
)}
</div>
);
};
export default Footer;

View File

@@ -0,0 +1,19 @@
import { ErrorIcon, LogIcon, LogInfoIcon, SucessIcon, WarningIcon } from "../icons/LogIcons";
import { LogType } from "../ui/log/LoggerContext";
export const GetLogIcon = (type: LogType): JSX.Element => {
switch (type) {
case "info":
return <LogInfoIcon />;
case "log":
return <LogIcon />;
case "error":
return <ErrorIcon />;
case "warning":
return <WarningIcon />;
case "success":
return <SucessIcon />;
default:
return <LogIcon />;
}
};

Some files were not shown because too many files have changed in this diff Show More