From 7ad9e5bc9956d2a9b64eb1571dba5b3e494a4d63 Mon Sep 17 00:00:00 2001 From: Albert Stefanov Date: Fri, 19 Dec 2025 22:24:29 +0200 Subject: [PATCH 1/2] Refactor: part 1 Some code-smell cleanup Strong typing (got to .ts in the end...) Merging some 2-line files and 1-file directories... --- eslint.config.js | 71 +- package.json | 55 +- src/App.jsx | 55 - src/App.tsx | 49 + src/config.js | 28 - src/config.ts | 53 + src/fauna-types.d.ts | 14 + src/globals.d.ts | 9 + src/helpers.ts | 8 + src/hooks/useActionLog.js | 5 - src/hooks/useAuthStorage.js | 95 - src/hooks/useAuthStorage.ts | 95 + src/hooks/useAuthenticatedSWR.js | 10 - src/hooks/useCurrentUser.js | 5 - src/hooks/useDeviceAction.js | 24 - src/hooks/useDeviceAction.ts | 18 + src/hooks/useDevices.js | 5 - src/hooks/useEndpoints.ts | 38 + src/hooks/useMqttStatus.js | 6 - src/hooks/usePresentUsers.js | 6 - ...{useRememberPage.js => useRememberPage.ts} | 24 +- src/hooks/useVariant.js | 26 - src/hooks/useVariant.ts | 13 + src/{i18n.js => i18n.ts} | 2 +- src/layout/{Footer.jsx => Footer.tsx} | 0 src/layout/{NavBar.jsx => NavBar.tsx} | 97 +- src/{main.jsx => main.tsx} | 10 +- src/node.d.ts | 10 + src/{oauth.js => oauth.ts} | 4 +- src/pages/ActionLog.jsx | 54 - src/pages/ActionLog.tsx | 36 + src/pages/Dashboard.jsx | 14 - src/pages/Dashboard/InitLabDashboard.jsx | 11 - src/pages/{Devices.jsx => Devices.tsx} | 48 +- src/pages/Doors.jsx | 8 - src/pages/Hvac.jsx | 8 - src/pages/Lights.jsx | 8 - src/pages/Login.jsx | 30 - src/pages/Login.tsx | 27 + src/pages/Logout.jsx | 40 - src/pages/Logout.tsx | 35 + .../{OauthCallback.jsx => OauthCallback.tsx} | 26 +- src/pages/{Sensors.jsx => Sensors.tsx} | 20 +- src/portier-types.d.ts | 29 + src/types.d.ts | 9 + src/utils/device.js | 52 - src/utils/device.ts | 38 + src/utils/swr.js | 61 - src/utils/swr.ts | 53 + src/utils/time.js | 1 - src/utils/useDateTimeFormatter.js | 17 - src/utils/useDateTimeFormatter.ts | 16 + src/widgets/ActionLog/ActionLogEntry.jsx | 60 - src/widgets/ActionLog/ActionLogEntry.tsx | 40 + src/widgets/ActionLog/ActionLogTable.tsx | 29 + .../Dashboards/ColibriDashboard.tsx} | 0 src/widgets/Dashboards/InitLabDashboard.tsx | 11 + .../DeviceActionButton/DeviceActionButton.jsx | 113 - .../DeviceActionButton/DeviceActionButton.tsx | 67 + src/widgets/ErrorMessage.jsx | 19 - src/widgets/ErrorMessage.tsx | 13 + src/widgets/LoadingIcon.tsx | 6 + src/widgets/PresentUsers/PresentUserCard.tsx | 34 + src/widgets/PresentUsers/PresentUsers.jsx | 60 - src/widgets/PresentUsers/PresentUsers.scss | 5 - .../PresentUsers.tsx} | 16 +- .../PresentUsers/PresentUsersTable.css | 3 + .../PresentUsers/PresentUsersTable.tsx | 23 + src/widgets/RedirectToLogin.jsx | 11 - src/widgets/RedirectToLogin.tsx | 8 + src/widgets/RequireLoggedIn.tsx | 22 + src/widgets/RequireRole.jsx | 23 - src/widgets/RequireRole.tsx | 10 + src/widgets/RequireVariant.tsx | 8 + src/widgets/Route/RequireLoggedIn.jsx | 35 - src/widgets/SensorReading/SensorReading.jsx | 117 - .../SensorReading/SensorReadingValue.jsx | 16 - .../SensorPanel.css} | 0 src/widgets/SensorReadings/SensorPanel.tsx | 114 + src/widgets/SensorReadings/SensorReadings.tsx | 73 + .../SensorReadingsWrapper.jsx | 54 - src/widgets/icons/BusyIcon.jsx | 7 - src/widgets/icons/DoorClosedIcon.jsx | 7 - src/widgets/icons/DoorOpenIcon.jsx | 7 - src/widgets/icons/LoadingIcon.jsx | 16 - src/widgets/icons/LockIcon.jsx | 7 - src/widgets/icons/UnlockIcon.jsx | 7 - src/widgets/icons/WarningIcon.jsx | 7 - tsconfig.json | 26 + vite.config.js | 10 +- yarn.lock | 3438 ++++++++++++----- 91 files changed, 3576 insertions(+), 2422 deletions(-) delete mode 100644 src/App.jsx create mode 100644 src/App.tsx delete mode 100644 src/config.js create mode 100644 src/config.ts create mode 100644 src/fauna-types.d.ts create mode 100644 src/globals.d.ts create mode 100644 src/helpers.ts delete mode 100644 src/hooks/useActionLog.js delete mode 100644 src/hooks/useAuthStorage.js create mode 100644 src/hooks/useAuthStorage.ts delete mode 100644 src/hooks/useAuthenticatedSWR.js delete mode 100644 src/hooks/useCurrentUser.js delete mode 100644 src/hooks/useDeviceAction.js create mode 100644 src/hooks/useDeviceAction.ts delete mode 100644 src/hooks/useDevices.js create mode 100644 src/hooks/useEndpoints.ts delete mode 100644 src/hooks/useMqttStatus.js delete mode 100644 src/hooks/usePresentUsers.js rename src/hooks/{useRememberPage.js => useRememberPage.ts} (64%) delete mode 100644 src/hooks/useVariant.js create mode 100644 src/hooks/useVariant.ts rename src/{i18n.js => i18n.ts} (90%) rename src/layout/{Footer.jsx => Footer.tsx} (100%) rename src/layout/{NavBar.jsx => NavBar.tsx} (54%) rename src/{main.jsx => main.tsx} (67%) create mode 100644 src/node.d.ts rename src/{oauth.js => oauth.ts} (94%) delete mode 100644 src/pages/ActionLog.jsx create mode 100644 src/pages/ActionLog.tsx delete mode 100644 src/pages/Dashboard.jsx delete mode 100644 src/pages/Dashboard/InitLabDashboard.jsx rename src/pages/{Devices.jsx => Devices.tsx} (60%) delete mode 100644 src/pages/Doors.jsx delete mode 100644 src/pages/Hvac.jsx delete mode 100644 src/pages/Lights.jsx delete mode 100644 src/pages/Login.jsx create mode 100644 src/pages/Login.tsx delete mode 100644 src/pages/Logout.jsx create mode 100644 src/pages/Logout.tsx rename src/pages/{OauthCallback.jsx => OauthCallback.tsx} (52%) rename src/pages/{Sensors.jsx => Sensors.tsx} (54%) create mode 100644 src/portier-types.d.ts create mode 100644 src/types.d.ts delete mode 100644 src/utils/device.js create mode 100644 src/utils/device.ts delete mode 100644 src/utils/swr.js create mode 100644 src/utils/swr.ts delete mode 100644 src/utils/time.js delete mode 100644 src/utils/useDateTimeFormatter.js create mode 100644 src/utils/useDateTimeFormatter.ts delete mode 100644 src/widgets/ActionLog/ActionLogEntry.jsx create mode 100644 src/widgets/ActionLog/ActionLogEntry.tsx create mode 100644 src/widgets/ActionLog/ActionLogTable.tsx rename src/{pages/Dashboard/ColibriDashboard.jsx => widgets/Dashboards/ColibriDashboard.tsx} (100%) create mode 100644 src/widgets/Dashboards/InitLabDashboard.tsx delete mode 100644 src/widgets/DeviceActionButton/DeviceActionButton.jsx create mode 100644 src/widgets/DeviceActionButton/DeviceActionButton.tsx delete mode 100644 src/widgets/ErrorMessage.jsx create mode 100644 src/widgets/ErrorMessage.tsx create mode 100644 src/widgets/LoadingIcon.tsx create mode 100644 src/widgets/PresentUsers/PresentUserCard.tsx delete mode 100644 src/widgets/PresentUsers/PresentUsers.jsx delete mode 100644 src/widgets/PresentUsers/PresentUsers.scss rename src/widgets/{PresentUsersWrapper/PresentUsersWrapper.jsx => PresentUsers/PresentUsers.tsx} (80%) create mode 100644 src/widgets/PresentUsers/PresentUsersTable.css create mode 100644 src/widgets/PresentUsers/PresentUsersTable.tsx delete mode 100644 src/widgets/RedirectToLogin.jsx create mode 100644 src/widgets/RedirectToLogin.tsx create mode 100644 src/widgets/RequireLoggedIn.tsx delete mode 100644 src/widgets/RequireRole.jsx create mode 100644 src/widgets/RequireRole.tsx create mode 100644 src/widgets/RequireVariant.tsx delete mode 100644 src/widgets/Route/RequireLoggedIn.jsx delete mode 100644 src/widgets/SensorReading/SensorReading.jsx delete mode 100644 src/widgets/SensorReading/SensorReadingValue.jsx rename src/widgets/{SensorReading/SensorReading.css => SensorReadings/SensorPanel.css} (100%) create mode 100644 src/widgets/SensorReadings/SensorPanel.tsx create mode 100644 src/widgets/SensorReadings/SensorReadings.tsx delete mode 100644 src/widgets/SensorReadingsWrapper/SensorReadingsWrapper.jsx delete mode 100644 src/widgets/icons/BusyIcon.jsx delete mode 100644 src/widgets/icons/DoorClosedIcon.jsx delete mode 100644 src/widgets/icons/DoorOpenIcon.jsx delete mode 100644 src/widgets/icons/LoadingIcon.jsx delete mode 100644 src/widgets/icons/LockIcon.jsx delete mode 100644 src/widgets/icons/UnlockIcon.jsx delete mode 100644 src/widgets/icons/WarningIcon.jsx create mode 100644 tsconfig.json diff --git a/eslint.config.js b/eslint.config.js index 238d2e4..be7211e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -3,36 +3,49 @@ import globals from 'globals' import react from 'eslint-plugin-react' import reactHooks from 'eslint-plugin-react-hooks' import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from "@typescript-eslint/eslint-plugin" +import tsparser from "@typescript-eslint/parser" export default [ - { ignores: ['dist'] }, - { - files: ['**/*.{js,jsx}'], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - parserOptions: { - ecmaVersion: 'latest', - ecmaFeatures: { jsx: true }, - sourceType: 'module', - }, + { + ignores: ['dist'], + files: ['**/*.{js,jsx,ts,tsx}'], + languageOptions: { + parser: tsparser, + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: {jsx: true}, + sourceType: 'module', + }, + }, + settings: {react: {version: 'detect'}}, + plugins: { + react, + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + '@typescript-eslint': tseslint, + }, + // extends: [ + // "eslint:recommended", + // "next/core-web-vitals", + // "plugin:react/recommended", + // "standard-with-typescript", + // "plugin:@typescript-eslint/recommended", + // ], + rules: { + ...js.configs.recommended.rules, + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + ...reactHooks.configs.recommended.rules, + '@typescript-eslint/no-unused-vars': 'error', + 'no-unused-vars': 'off', + 'react/jsx-no-target-blank': 'off', + 'react-refresh/only-export-components': [ + 'warn', + {allowConstantExport: true}, + ], + }, }, - settings: { react: { version: '18.3' } }, - plugins: { - react, - 'react-hooks': reactHooks, - 'react-refresh': reactRefresh, - }, - rules: { - ...js.configs.recommended.rules, - ...react.configs.recommended.rules, - ...react.configs['jsx-runtime'].rules, - ...reactHooks.configs.recommended.rules, - 'react/jsx-no-target-blank': 'off', - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, - }, ] diff --git a/package.json b/package.json index b65a053..4e7b850 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --mode production", "build": "vite build", "lint": "eslint .", "preview": "vite preview" @@ -16,32 +16,39 @@ "bootstrap": "^5.3.3", "bootswatch": "^5.3.3", "date-fns": "^4.1.0", - "i18next": "^23.15.1", - "i18next-http-backend": "^2.6.1", - "js-pkce": "^1.4.0", - "js-yaml": "^4.1.0", - "oidc-client-ts": "^3.0.1", + "i18next": "^25.7.3", + "i18next-http-backend": "^3.0.2", + "js-pkce": "^2.0.0", + "js-yaml": "^4.1.1", + "oidc-client-ts": "^3.4.1", "prop-types": "^15.8.1", - "react": "^18.3.1", - "react-bootstrap": "^2.10.4", - "react-dom": "^18.3.1", - "react-i18next": "^15.0.2", - "react-oidc-context": "^3.1.1", - "react-router-dom": "^6.26.2", - "sass": "^1.79.1", - "swr": "^2.2.5", + "react": "^19.2.3", + "react-bootstrap": "^2.10.10", + "react-dom": "^19.2.3", + "react-i18next": "^16.5.0", + "react-oidc-context": "^3.3.0", + "react-router-dom": "^7.11.0", + "sass": "^1.97.0", + "swr": "^2.3.8", "vite-plugin-compression": "^0.5.1" }, "devDependencies": { - "@eslint/js": "^9.9.0", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.1", - "eslint": "^9.9.0", - "eslint-plugin-react": "^7.35.0", - "eslint-plugin-react-hooks": "^5.1.0-rc.0", - "eslint-plugin-react-refresh": "^0.4.9", - "globals": "^15.9.0", - "vite": "^5.4.1" + "typescript":">=4.0.0", + "@eslint/js": "^9.39.2", + "@tsconfig/vite-react": "^7.0.2", + "@types/js-yaml": "^4.0.9", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@types/web": "^0.0.303", + "@typescript-eslint/eslint-plugin": "^8.50.0", + "@typescript-eslint/parser": "^8.50.0", + "@vitejs/plugin-react": "^5.1.2", + "eslint": "^9.39.2", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.26", + "globals": "^16.5.0", + "typescript-plugin-css-modules": "^5.2.0", + "vite": "^7.3.0" } } diff --git a/src/App.jsx b/src/App.jsx deleted file mode 100644 index 8b68d58..0000000 --- a/src/App.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useEffect } from 'react'; -import { Container } from 'react-bootstrap'; -import { Route, Routes } from 'react-router-dom'; - -import Dashboard from './pages/Dashboard.jsx'; -import NavBar from './layout/NavBar.jsx'; -import Footer from './layout/Footer.jsx'; -import Sensors from './pages/Sensors.jsx'; -import Doors from './pages/Doors.jsx'; -import OauthCallback from './pages/OauthCallback.jsx'; -import Logout from './pages/Logout.jsx'; -import Login from './pages/Login.jsx'; -import RequireLoggedIn from './widgets/Route/RequireLoggedIn.jsx'; -import ActionLog from './pages/ActionLog.jsx'; -import Lights from './pages/Lights.jsx'; -import Hvac from './pages/Hvac.jsx'; -import { useVariant } from './hooks/useVariant.js'; - -function App() { - const variant = useVariant(); - - useEffect(() => { - if (variant === 'colibri') { - document.title = 'Casa Libri'; - } - }, [variant]); - - return (<> - -
- - - } /> - - - } /> - - - } /> - - - } /> - } /> - } /> - } /> - } /> - } /> - - -
-