From 1621f90f0c96f57f7030032c0c44e742e9eb198b Mon Sep 17 00:00:00 2001 From: vasich Date: Sun, 11 Aug 2024 01:43:00 +0700 Subject: [PATCH] frontend improvements, yandex model iimplementations --- Db/{ => old}/init.sql | Bin .../Yuna.Website.Server/API/AuthEndpoints.cs | 13 ++++++ .../Infrastructure/CookieExtensions.cs | 19 ++++++++- .../Infrastructure/CookieUserModel.cs | 3 ++ .../Infrastructure/Settings.cs | 6 ++- .../Model/DeviceMapping.cs | 12 ++++++ .../Model/YandexDevice/YandexDeviceTypes.cs | 9 ++++ .../Model/YandexDevice/YandexExtensions.cs | 30 ++++++++++++++ .../Model/YandexDevice/YandexParameter.cs | 13 ++++++ .../Model/YandexDevice/YandexProp.cs | 33 +++++++++++++++ .../Model/YandexDevice/YandexPropType.cs | 7 ++++ .../MappingService/IMappingService.cs | 6 +++ Yuna.Website/Yuna.Website.Server/Starter.cs | 6 +-- .../Yuna.Website.Server.csproj | 2 +- .../yuna.website.client/package-lock.json | 16 +++++++ Yuna.Website/yuna.website.client/package.json | 6 ++- .../src/components/Header.tsx | 39 +++++++++++++++++- .../yuna.website.client/src/global.d.ts | 9 ++++ Yuna.Website/yuna.website.client/src/main.tsx | 3 ++ .../src/pages/home/HomePage.tsx | 2 - .../src/pages/home/components/DeviceList.tsx | 4 +- .../src/pages/login/LoginPage.tsx | 24 +++++++++++ .../src/pages/login/LoginPageService.ts | 6 +++ .../src/pages/login/LoginPageStore.ts | 3 +- .../src/pages/mappings/MappingsPage.tsx | 6 +++ .../src/resources/styles/common.scss | 9 ++++ .../src/resources/styles/header.scss | 26 +++++++++++- .../yuna.website.client/src/router.tsx | 26 ++++++++++-- .../src/utils/cookies/Yuna.ts | 26 ++++++++++++ 29 files changed, 344 insertions(+), 20 deletions(-) rename Db/{ => old}/init.sql (100%) create mode 100644 Yuna.Website/Yuna.Website.Server/Model/DeviceMapping.cs create mode 100644 Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexDeviceTypes.cs create mode 100644 Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexExtensions.cs create mode 100644 Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexParameter.cs create mode 100644 Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexProp.cs create mode 100644 Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexPropType.cs create mode 100644 Yuna.Website/Yuna.Website.Server/Services/MappingService/IMappingService.cs create mode 100644 Yuna.Website/yuna.website.client/src/global.d.ts create mode 100644 Yuna.Website/yuna.website.client/src/pages/mappings/MappingsPage.tsx create mode 100644 Yuna.Website/yuna.website.client/src/utils/cookies/Yuna.ts diff --git a/Db/init.sql b/Db/old/init.sql similarity index 100% rename from Db/init.sql rename to Db/old/init.sql diff --git a/Yuna.Website/Yuna.Website.Server/API/AuthEndpoints.cs b/Yuna.Website/Yuna.Website.Server/API/AuthEndpoints.cs index b28f596..e290020 100644 --- a/Yuna.Website/Yuna.Website.Server/API/AuthEndpoints.cs +++ b/Yuna.Website/Yuna.Website.Server/API/AuthEndpoints.cs @@ -26,6 +26,10 @@ namespace Yuna.Website.Server.API .Produces(200) .Produces(400); + app.MapPost("/api/auth/logout", Logout) + .WithTags("auth") + .Produces(200); + } @@ -37,9 +41,18 @@ namespace Yuna.Website.Server.API var hashedPassword = Encrypter.HashPassword(request.RawPassword, request.UserName); if (!hashedPassword.Equals(userFromDb.HashedPassword)) return Results.Unauthorized(); await SetAccessToken(context, tokenService, userFromDb); + SetFrontendCookie(userFromDb, context); return Results.Ok(""); } + public async Task Logout(HttpContext context, object? additionalInfo = null) + { + await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + context.ClearCookies(); + + return Results.Ok(); + } + private static async Task SetAccessToken(HttpContext context, ITokenService tokenService, User userFromDb) { diff --git a/Yuna.Website/Yuna.Website.Server/Infrastructure/CookieExtensions.cs b/Yuna.Website/Yuna.Website.Server/Infrastructure/CookieExtensions.cs index cba7c41..3c25698 100644 --- a/Yuna.Website/Yuna.Website.Server/Infrastructure/CookieExtensions.cs +++ b/Yuna.Website/Yuna.Website.Server/Infrastructure/CookieExtensions.cs @@ -24,13 +24,28 @@ namespace Yuna.Website.Server.Infrastructure return default!; } - public static void SaveToCookies(this HttpContext context, string key, T value, TimeSpan? maxAge = null) + public static void SaveToCookies(this HttpContext context, string key, T value, TimeSpan? maxAge = null, bool httpOnly = false) { var dataStr = System.Text.Json.JsonSerializer.Serialize(value); if (context.Request.Cookies.ContainsKey(key)) context.Response.Cookies.Delete(key); - context.Response.Cookies.Append(key, dataStr, new CookieOptions() { HttpOnly = true, MaxAge = maxAge ?? TimeSpan.FromDays(365) }); + var sameSite = !Settings.IsDevEnv; + + context.Response.Cookies.Append(key, dataStr, new CookieOptions() + { HttpOnly = httpOnly, + MaxAge = maxAge ?? TimeSpan.FromDays(365), + SameSite = sameSite ? SameSiteMode.Strict : SameSiteMode.None , + Secure = true + }); + } + + public static void ClearCookies(this HttpContext context) + { + foreach (var cookie in context.Request.Cookies) + { + context.Response.Cookies.Delete(cookie.Key); + } } public static long? GetUserIdFromCookie(this HttpContext context) diff --git a/Yuna.Website/Yuna.Website.Server/Infrastructure/CookieUserModel.cs b/Yuna.Website/Yuna.Website.Server/Infrastructure/CookieUserModel.cs index c0653ee..346e271 100644 --- a/Yuna.Website/Yuna.Website.Server/Infrastructure/CookieUserModel.cs +++ b/Yuna.Website/Yuna.Website.Server/Infrastructure/CookieUserModel.cs @@ -9,8 +9,11 @@ namespace Yuna.Website.Server.Infrastructure { Id = user.Id; Username = user.UserName; + IsAdmin = user.IsAdmin; } + [JsonPropertyName("isAdmin")] + public bool IsAdmin { get; } [JsonPropertyName("username")] public string Username { get; } diff --git a/Yuna.Website/Yuna.Website.Server/Infrastructure/Settings.cs b/Yuna.Website/Yuna.Website.Server/Infrastructure/Settings.cs index 36cb2e4..f633cd3 100644 --- a/Yuna.Website/Yuna.Website.Server/Infrastructure/Settings.cs +++ b/Yuna.Website/Yuna.Website.Server/Infrastructure/Settings.cs @@ -10,10 +10,14 @@ namespace Yuna.Website.Server.Infrastructure public static string ReferalCode { get; private set; } = null!; public static string DbConnectionStr { get; private set; } = null!; + public static bool IsDevEnv { get; private set; } = false; + public static bool IsProduction => !IsDevEnv; public static string HttpsExternalUrl { get; private set; } = null!; - public static void Init() + public static void Init(bool isDev = true) { + IsDevEnv = isDev; + var jsonText = File.ReadAllText("globalSettings.json"); using JsonDocument document = JsonDocument.Parse(jsonText); diff --git a/Yuna.Website/Yuna.Website.Server/Model/DeviceMapping.cs b/Yuna.Website/Yuna.Website.Server/Model/DeviceMapping.cs new file mode 100644 index 0000000..68e55f5 --- /dev/null +++ b/Yuna.Website/Yuna.Website.Server/Model/DeviceMapping.cs @@ -0,0 +1,12 @@ +using Yuna.Website.Server.Model.YandexDevice; + +namespace Yuna.Website.Server.Model +{ + public class DeviceMapping + { + public YandexDeviceType DeviceType { get; set; } + public Device Device { get; set; } + public Dictionary PropMappings { get; set; } + + } +} diff --git a/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexDeviceTypes.cs b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexDeviceTypes.cs new file mode 100644 index 0000000..ac8a9f6 --- /dev/null +++ b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexDeviceTypes.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace Yuna.Website.Server.Model.YandexDevice +{ + public enum YandexDeviceType + { + ClimateSensor = 0 + } +} diff --git a/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexExtensions.cs b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexExtensions.cs new file mode 100644 index 0000000..e48333a --- /dev/null +++ b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexExtensions.cs @@ -0,0 +1,30 @@ +namespace Yuna.Website.Server.Model.YandexDevice +{ + public static class YandexExtensions + { + public static string ToJsonName(this YandexDeviceType type) + { + switch(type) + { + case YandexDeviceType.ClimateSensor: + return "sensor.climate"; + + default: + return "yuna_error"; + } + } + + public static string ToJsonName(this YandexPropType type) + { + switch (type) + { + case YandexPropType.Float: + return "float"; + + default: + return "yuna_error"; + } + } + } +} + \ No newline at end of file diff --git a/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexParameter.cs b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexParameter.cs new file mode 100644 index 0000000..3dc9525 --- /dev/null +++ b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexParameter.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace Yuna.Website.Server.Model.YandexDevice +{ + public class YandexParameter + { + [JsonPropertyName("instance")] + public string Instance { get; set; } + + [JsonPropertyName("unit")] + public string Unit { get; set; } + } +} diff --git a/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexProp.cs b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexProp.cs new file mode 100644 index 0000000..7624e8d --- /dev/null +++ b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexProp.cs @@ -0,0 +1,33 @@ +using System.Text.Json.Serialization; + +namespace Yuna.Website.Server.Model.YandexDevice +{ + public class YandexProp + { + public YandexProp() + { } + + public YandexProp(YandexPropType type, bool retrievable, bool reportable, YandexParameter parameter) + { + Type = type; + Retrievable = retrievable; + Reportable = reportable; + Parameter = parameter; + } + + [JsonIgnore] + public YandexPropType Type { get; set; } + + [JsonPropertyName("type")] + public string JsonPropName => Type.ToJsonName(); + + [JsonPropertyName("retrievable")] + public bool Retrievable { get; set; } = true; + + [JsonPropertyName("reportable")] + public bool Reportable { get; set; } = true; + + [JsonPropertyName("parameters")] + public YandexParameter Parameter { get; set; } = null!; + } +} diff --git a/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexPropType.cs b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexPropType.cs new file mode 100644 index 0000000..3bf4ea8 --- /dev/null +++ b/Yuna.Website/Yuna.Website.Server/Model/YandexDevice/YandexPropType.cs @@ -0,0 +1,7 @@ +namespace Yuna.Website.Server.Model.YandexDevice +{ + public enum YandexPropType + { + Float = 0, + } +} diff --git a/Yuna.Website/Yuna.Website.Server/Services/MappingService/IMappingService.cs b/Yuna.Website/Yuna.Website.Server/Services/MappingService/IMappingService.cs new file mode 100644 index 0000000..9aa1444 --- /dev/null +++ b/Yuna.Website/Yuna.Website.Server/Services/MappingService/IMappingService.cs @@ -0,0 +1,6 @@ +namespace Yuna.Website.Server.Services.MappingService +{ + public interface IMappingService + { + } +} diff --git a/Yuna.Website/Yuna.Website.Server/Starter.cs b/Yuna.Website/Yuna.Website.Server/Starter.cs index eb1cb86..12548c4 100644 --- a/Yuna.Website/Yuna.Website.Server/Starter.cs +++ b/Yuna.Website/Yuna.Website.Server/Starter.cs @@ -18,7 +18,7 @@ namespace Yuna.Website.Server { public static void LoadConfigs(WebApplicationBuilder builder) { - Settings.Init(); + Settings.Init(builder.Environment.IsDevelopment()); } /// @@ -206,8 +206,8 @@ namespace Yuna.Website.Server .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials() - .SetIsOriginAllowed(origin => true) // Разрешить все источники - .WithExposedHeaders("Location")); // Разрешить заголовок Location) + .SetIsOriginAllowed(origin => true) // Разрешить все источники + .WithExposedHeaders("Location")); // Разрешить заголовок Location) } diff --git a/Yuna.Website/Yuna.Website.Server/Yuna.Website.Server.csproj b/Yuna.Website/Yuna.Website.Server/Yuna.Website.Server.csproj index 8d4f046..1a0e2ca 100644 --- a/Yuna.Website/Yuna.Website.Server/Yuna.Website.Server.csproj +++ b/Yuna.Website/Yuna.Website.Server/Yuna.Website.Server.csproj @@ -8,7 +8,7 @@ ..\.. ..\yuna.website.client npm run dev - https://localhost:5173 + https://192.168.1.2:5173 diff --git a/Yuna.Website/yuna.website.client/package-lock.json b/Yuna.Website/yuna.website.client/package-lock.json index 2eb5f2f..f2e2fb7 100644 --- a/Yuna.Website/yuna.website.client/package-lock.json +++ b/Yuna.Website/yuna.website.client/package-lock.json @@ -10,12 +10,14 @@ "dependencies": { "@chakra-ui/react": "^2.8.2", "axios": "^1.7.2", + "js-cookie": "^3.0.5", "mobx": "^6.13.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" }, "devDependencies": { + "@types/js-cookie": "^3.0.6", "@types/node": "^20.12.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", @@ -2582,6 +2584,12 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true + }, "node_modules/@types/lodash": { "version": "4.17.6", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", @@ -4153,6 +4161,14 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/Yuna.Website/yuna.website.client/package.json b/Yuna.Website/yuna.website.client/package.json index 68534bc..65a83ae 100644 --- a/Yuna.Website/yuna.website.client/package.json +++ b/Yuna.Website/yuna.website.client/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --host 192.168.1.2 --port 5173", "build": "tsc -b && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" @@ -12,12 +12,14 @@ "dependencies": { "@chakra-ui/react": "^2.8.2", "axios": "^1.7.2", + "js-cookie": "^3.0.5", "mobx": "^6.13.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" }, "devDependencies": { + "@types/js-cookie": "^3.0.6", "@types/node": "^20.12.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", @@ -31,4 +33,4 @@ "typescript": "^5.2.2", "vite": "^5.3.1" } -} +} \ No newline at end of file diff --git a/Yuna.Website/yuna.website.client/src/components/Header.tsx b/Yuna.Website/yuna.website.client/src/components/Header.tsx index 604cfaa..d16daab 100644 --- a/Yuna.Website/yuna.website.client/src/components/Header.tsx +++ b/Yuna.Website/yuna.website.client/src/components/Header.tsx @@ -1,6 +1,18 @@ +import { useNavigate } from "react-router-dom"; import "../resources/styles/header.scss" +import { yunaGlobal } from "../utils/cookies/Yuna"; +import { Button, Icon, IconButton } from "@chakra-ui/react"; +import { MdOutlineLogout } from "react-icons/md"; +import { LoginPageService } from "../pages/login/LoginPageService"; export const Header = () => { + const navigate = useNavigate(); + + const onLogout = async () => { + await LoginPageService.logout(); + navigate("/login"); + } + return (
{ paddingTop: 10 }}>
-

Yuna

-
); +

navigate("/")}>Yuna

+ +
+ {'Приветик, ' + yunaGlobal.user?.username} + } + size='sm' + color="black" + colorScheme="white" + aria-label={"logout"} + onClick={() => onLogout()} /> + {yunaGlobal.user?.isAdmin && Ого, ты админ 💅} +
+ + ); } \ No newline at end of file diff --git a/Yuna.Website/yuna.website.client/src/global.d.ts b/Yuna.Website/yuna.website.client/src/global.d.ts new file mode 100644 index 0000000..dda0ec1 --- /dev/null +++ b/Yuna.Website/yuna.website.client/src/global.d.ts @@ -0,0 +1,9 @@ +import { Yuna } from "./utils/cookies/Yuna"; + + +declare global { + // eslint-disable-next-line no-var + var yuna: Yuna; +} + +export { } \ No newline at end of file diff --git a/Yuna.Website/yuna.website.client/src/main.tsx b/Yuna.Website/yuna.website.client/src/main.tsx index fa2be3b..b413616 100644 --- a/Yuna.Website/yuna.website.client/src/main.tsx +++ b/Yuna.Website/yuna.website.client/src/main.tsx @@ -3,6 +3,9 @@ import ReactDOM from 'react-dom/client' import { RouterProvider } from 'react-router-dom' import "./resources/styles/common.scss" import { router } from './router' +import { yunaGlobal } from './utils/cookies/Yuna' + +globalThis.yuna = yunaGlobal; ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/Yuna.Website/yuna.website.client/src/pages/home/HomePage.tsx b/Yuna.Website/yuna.website.client/src/pages/home/HomePage.tsx index 4b2f05b..6dc65d2 100644 --- a/Yuna.Website/yuna.website.client/src/pages/home/HomePage.tsx +++ b/Yuna.Website/yuna.website.client/src/pages/home/HomePage.tsx @@ -5,8 +5,6 @@ import { EditModal } from "./components/modals/EditModal"; export const HomePage = () => { return ( <> - -
diff --git a/Yuna.Website/yuna.website.client/src/pages/home/components/DeviceList.tsx b/Yuna.Website/yuna.website.client/src/pages/home/components/DeviceList.tsx index ba9dfa5..604f834 100644 --- a/Yuna.Website/yuna.website.client/src/pages/home/components/DeviceList.tsx +++ b/Yuna.Website/yuna.website.client/src/pages/home/components/DeviceList.tsx @@ -11,10 +11,10 @@ export const DeviceList = observer(() => { }, []) return ( - < main className="main" > + < > {homePageStore.isLoading ? : homePageStore.devices.length > 0 && homePageStore.devices.map(x => ) } - ); + ); }); \ No newline at end of file diff --git a/Yuna.Website/yuna.website.client/src/pages/login/LoginPage.tsx b/Yuna.Website/yuna.website.client/src/pages/login/LoginPage.tsx index 26b2ec9..d7f89ce 100644 --- a/Yuna.Website/yuna.website.client/src/pages/login/LoginPage.tsx +++ b/Yuna.Website/yuna.website.client/src/pages/login/LoginPage.tsx @@ -2,9 +2,29 @@ import { Button, Center, Input, Spinner } from "@chakra-ui/react"; import "../../resources/styles/loginPage.scss" import { observer } from "mobx-react" import { LoginPageStore } from "./LoginPageStore"; +import { useRef } from "react"; const store = new LoginPageStore(); export const LoginPage = observer(() => { + + const loginRef = useRef(null); + const passwordRef = useRef(null); + + const handleKeyDown = (key: string) => { + if (key === "ArrowDown") { + if (document.activeElement === loginRef.current) { + passwordRef.current?.focus(); + } + } else if (key === "ArrowUp") { + if (document.activeElement === passwordRef.current) { + loginRef.current?.focus(); + } + } + + else if (key === "Enter") store.handleLogin(); + }; + + return (
@@ -22,14 +42,18 @@ export const LoginPage = observer(() => { : <> store.setLogin(e.target.value)} + onKeyDown={x => handleKeyDown(x.key)} marginBottom={5} /> handleKeyDown(x.key)} value={store.password} onChange={e => store.setPassword(e.target.value)} /> } diff --git a/Yuna.Website/yuna.website.client/src/pages/login/LoginPageService.ts b/Yuna.Website/yuna.website.client/src/pages/login/LoginPageService.ts index 07cdf69..425843b 100644 --- a/Yuna.Website/yuna.website.client/src/pages/login/LoginPageService.ts +++ b/Yuna.Website/yuna.website.client/src/pages/login/LoginPageService.ts @@ -22,6 +22,12 @@ export class LoginPageService { } } + public static async logout(): Promise { + const response = await api.post("auth/logout"); + if (response.status === 200) return true; + return false; + } + public static async loginOauth(request: IOauthLoginRequest): Promise { diff --git a/Yuna.Website/yuna.website.client/src/pages/login/LoginPageStore.ts b/Yuna.Website/yuna.website.client/src/pages/login/LoginPageStore.ts index 1884d84..811635a 100644 --- a/Yuna.Website/yuna.website.client/src/pages/login/LoginPageStore.ts +++ b/Yuna.Website/yuna.website.client/src/pages/login/LoginPageStore.ts @@ -7,6 +7,7 @@ import { IOauthQueryParams } from "./types"; export class LoginPageStore { + toast = createStandaloneToast(); login: string = ""; password: string = ""; @@ -84,7 +85,7 @@ export class LoginPageStore { return; } - window.location.replace("https://localhost:5173"); + window.location.replace("/"); } diff --git a/Yuna.Website/yuna.website.client/src/pages/mappings/MappingsPage.tsx b/Yuna.Website/yuna.website.client/src/pages/mappings/MappingsPage.tsx new file mode 100644 index 0000000..107f0fe --- /dev/null +++ b/Yuna.Website/yuna.website.client/src/pages/mappings/MappingsPage.tsx @@ -0,0 +1,6 @@ +import { observer } from "mobx-react" + +export const MappingsPage = observer(() => { + return <> + +}) \ No newline at end of file diff --git a/Yuna.Website/yuna.website.client/src/resources/styles/common.scss b/Yuna.Website/yuna.website.client/src/resources/styles/common.scss index 9c8e6c6..f40d247 100644 --- a/Yuna.Website/yuna.website.client/src/resources/styles/common.scss +++ b/Yuna.Website/yuna.website.client/src/resources/styles/common.scss @@ -1,5 +1,6 @@ * { font-family: 'Montserrat'; + } .container_wrapper { @@ -15,4 +16,12 @@ font-display: block; font-family: 'Montserrat'; src: url(../fonts/Montserrat-VariableFont_wght.ttf); +} + +.micro-text { + font-size: 10px; +} + +.important { + color: red; } \ No newline at end of file diff --git a/Yuna.Website/yuna.website.client/src/resources/styles/header.scss b/Yuna.Website/yuna.website.client/src/resources/styles/header.scss index a98d3f3..75deb91 100644 --- a/Yuna.Website/yuna.website.client/src/resources/styles/header.scss +++ b/Yuna.Website/yuna.website.client/src/resources/styles/header.scss @@ -2,6 +2,9 @@ position: fixed; background: #4FD1C5; border-radius: 10px; + display: flex; + flex-direction: row; + align-items: center; //border-bottom: solid black 1px; width: 80%; height: 70px; @@ -10,10 +13,31 @@ /* x-offset y-offset blur-radius color */ h1 { - padding-top: 10px; + transition: color 0.3s; font-size: 30px; padding-left: 30px; } + h1:hover { + cursor: pointer; + color: white; + } + + nav { + display: flex; + flex-direction: row; + padding-top: 10px; + padding-left: 30px; + + a { + color: black; + transition: color 0.3s; + } + + a:hover { + cursor: pointer; + color: white; + } + } } \ No newline at end of file diff --git a/Yuna.Website/yuna.website.client/src/router.tsx b/Yuna.Website/yuna.website.client/src/router.tsx index 966ec09..6ab3ac1 100644 --- a/Yuna.Website/yuna.website.client/src/router.tsx +++ b/Yuna.Website/yuna.website.client/src/router.tsx @@ -1,8 +1,10 @@ import { ChakraProvider } from "@chakra-ui/react"; -import { Outlet, createBrowserRouter } from "react-router-dom"; +import { Navigate, Outlet, createBrowserRouter } from "react-router-dom"; import { LoginPage } from "./pages/login/LoginPage"; import { YunaTheme } from "./theme"; import { HomePage } from "./pages/home/HomePage"; +import { MappingsPage } from "./pages/mappings/MappingsPage"; +import { Header } from "./components/Header"; @@ -13,13 +15,31 @@ export const router = createBrowserRouter([ errorElement:

Something gone wrong

, children: [ + { + path: "/", + element: + }, { path: "home", - element: + element: <> +
+
+ +
+ + }, + { + path: "mappings", + element: <> +
+
+ +
+ }, { path: "settings", - element: <>set + element: <>
set }, { path: "login", diff --git a/Yuna.Website/yuna.website.client/src/utils/cookies/Yuna.ts b/Yuna.Website/yuna.website.client/src/utils/cookies/Yuna.ts new file mode 100644 index 0000000..ae23875 --- /dev/null +++ b/Yuna.Website/yuna.website.client/src/utils/cookies/Yuna.ts @@ -0,0 +1,26 @@ +import Cookies from 'js-cookie'; + +class Yuna { + + getUser() { + const cookieStr = Cookies.get("user"); + if (cookieStr) { + const decodedCookie = decodeURIComponent(cookieStr); + return JSON.parse(decodedCookie) as IUserCookie; + } + + return undefined; + } + + user: IUserCookie | undefined = this.getUser() + +} + +export const yunaGlobal = new Yuna(); + + +interface IUserCookie { + isAdmin: boolean + username: string, + id: number +} \ No newline at end of file