From b282bfe64fff2944571cd6c208ab5c6987824e3f Mon Sep 17 00:00:00 2001 From: orangecoding Date: Sun, 28 Sep 2025 21:38:54 +0200 Subject: [PATCH 1/5] first draft of ui redesign --- lib/api/routes/versionRouter.js | 9 +- package.json | 2 +- ui/src/App.jsx | 146 ++++++++++-------- ui/src/App.less | 9 +- ui/src/components/footer/FredyFooter.jsx | 19 +++ ui/src/components/footer/FredyFooter.less | 17 ++ ui/src/components/logout/Logout.jsx | 24 +-- ui/src/components/menu/Menu.jsx | 65 -------- ui/src/components/menu/Menu.less | 3 - ui/src/components/navigation/Navigate.less | 9 ++ ui/src/components/navigation/Navigation.jsx | 50 ++++++ ui/src/components/segment/SegmentPart.jsx | 1 + ui/src/components/segment/SegmentParts.less | 3 + ui/src/components/table/ListingsTable.jsx | 2 +- ui/src/components/version/VersionBanner.jsx | 17 +- ui/src/components/version/VersionBanner.less | 6 +- ui/src/hooks/screenWidth.js | 23 +++ .../views/generalSettings/GeneralSettings.jsx | 2 - ui/src/views/jobs/Jobs.jsx | 3 - ui/src/views/jobs/Jobs.less | 3 +- ui/src/views/jobs/ProcessingTimes.jsx | 79 +++++----- ui/src/views/jobs/ProsessingTimes.less | 5 + ui/src/views/user/Users.jsx | 2 +- ui/src/views/user/Users.less | 3 +- 24 files changed, 293 insertions(+), 209 deletions(-) create mode 100644 ui/src/components/footer/FredyFooter.jsx create mode 100644 ui/src/components/footer/FredyFooter.less delete mode 100644 ui/src/components/menu/Menu.jsx delete mode 100644 ui/src/components/menu/Menu.less create mode 100644 ui/src/components/navigation/Navigate.less create mode 100644 ui/src/components/navigation/Navigation.jsx create mode 100644 ui/src/hooks/screenWidth.js create mode 100644 ui/src/views/jobs/ProsessingTimes.less diff --git a/lib/api/routes/versionRouter.js b/lib/api/routes/versionRouter.js index 4a685e64..9810fbcb 100644 --- a/lib/api/routes/versionRouter.js +++ b/lib/api/routes/versionRouter.js @@ -8,7 +8,14 @@ const versionRouter = service.newRouter(); versionRouter.get('/', async (req, res) => { const versionPayload = await getCurrentVersionFromGithub(); - res.body = versionPayload == null ? { newVersion: false } : versionPayload; + const localFredyVersion = await getPackageVersion(); + res.body = + versionPayload == null + ? { + newVersion: false, + localFredyVersion, + } + : versionPayload; res.send(); }); diff --git a/package.json b/package.json index 02ac9dce..9c676404 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fredy", - "version": "12.3.2", + "version": "12.1.2", "description": "[F]ind [R]eal [E]states [d]amn eas[y].", "scripts": { "prepare": "husky", diff --git a/ui/src/App.jsx b/ui/src/App.jsx index fbfab609..8efd5faa 100644 --- a/ui/src/App.jsx +++ b/ui/src/App.jsx @@ -8,18 +8,19 @@ import UserMutator from './views/user/mutation/UserMutator'; import JobInsight from './views/jobs/insights/JobInsight.jsx'; import { useActions, useSelector } from './services/state/store'; import { Routes, Route, Navigate } from 'react-router-dom'; -import Logout from './components/logout/Logout'; -import Logo from './components/logo/Logo'; -import Menu from './components/menu/Menu'; import Login from './views/login/Login'; import Users from './views/user/Users'; import Jobs from './views/jobs/Jobs'; import './App.less'; import TrackingModal from './components/tracking/TrackingModal.jsx'; -import { Banner } from '@douyinfe/semi-ui'; +import { Banner, Divider } from '@douyinfe/semi-ui'; import VersionBanner from './components/version/VersionBanner.jsx'; import Listings from './views/listings/Listings.jsx'; +import Navigation from './components/navigation/Navigation.jsx'; +import { Layout } from '@douyinfe/semi-ui'; +import FredyFooter from './components/footer/FredyFooter.jsx'; +import ProcessingTimes from './views/jobs/ProcessingTimes.jsx'; export default function FredyApp() { const actions = useActions(); @@ -27,6 +28,7 @@ export default function FredyApp() { const currentUser = useSelector((state) => state.user.currentUser); const versionUpdate = useSelector((state) => state.versionUpdate.versionUpdate); const settings = useSelector((state) => state.generalSettings.settings); + const processingTimes = useSelector((state) => state.jobs.processingTimes); useEffect(() => { async function init() { @@ -50,6 +52,7 @@ export default function FredyApp() { }; const isAdmin = () => currentUser != null && currentUser.isAdmin; + const { Footer, Sider, Content } = Layout; return loading ? null : needsLogin() ? ( @@ -57,71 +60,80 @@ export default function FredyApp() { } /> ) : ( -
-
- - - - {versionUpdate?.newVersion && } - {settings.demoMode && ( - <> - -
- - )} - {settings.analyticsEnabled === null && !settings.demoMode && } - - } /> - } /> - } /> - } /> - } /> - } /> + + + + + + + {versionUpdate?.newVersion && } + {settings.demoMode && ( + <> + +
+ + )} + {settings.analyticsEnabled === null && !settings.demoMode && } + {processingTimes != null && } + +
+ + } /> + } /> + } /> + } /> + } /> + } /> - {/* Permission-aware routes */} - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> + {/* Permission-aware routes */} + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> - } /> - -
-
+ } /> + +
+ + + + ); } diff --git a/ui/src/App.less b/ui/src/App.less index c3bc3011..b9e881e8 100644 --- a/ui/src/App.less +++ b/ui/src/App.less @@ -1,12 +1,9 @@ .app { - display: flex; - flex-direction: column; + height: 100%; width: 100%; - &__container { - padding: 1rem 1rem; - color: var(--semi-color-text-0); - background-color: #232429; + &__content { + margin: 1rem; } } diff --git a/ui/src/components/footer/FredyFooter.jsx b/ui/src/components/footer/FredyFooter.jsx new file mode 100644 index 00000000..a5589ed3 --- /dev/null +++ b/ui/src/components/footer/FredyFooter.jsx @@ -0,0 +1,19 @@ +import React from 'react'; +import './FredyFooter.less'; +import { useSelector } from '../../services/state/store.js'; +import { Typography } from '@douyinfe/semi-ui'; + +export default function FredyFooter() { + const { Text } = Typography; + const version = useSelector((state) => state.versionUpdate.versionUpdate); + return ( +
+
+ Fredy V{version?.localFredyVersion || 'N/A'} +
+
+ Made with ❤️ +
+
+ ); +} diff --git a/ui/src/components/footer/FredyFooter.less b/ui/src/components/footer/FredyFooter.less new file mode 100644 index 00000000..5909fa8e --- /dev/null +++ b/ui/src/components/footer/FredyFooter.less @@ -0,0 +1,17 @@ +.fredyFooter { + background:rgb(53, 54, 60); + color: white; + display: flex; + justify-content: space-between; + align-items: center; + + &__version { + padding-left: .5rem; + font-size: small; + + } + &__copyRight { + padding-right: 1rem; + + } +} \ No newline at end of file diff --git a/ui/src/components/logout/Logout.jsx b/ui/src/components/logout/Logout.jsx index 24d41850..67de4bf0 100644 --- a/ui/src/components/logout/Logout.jsx +++ b/ui/src/components/logout/Logout.jsx @@ -4,17 +4,19 @@ import { xhrPost } from '../../services/xhr'; import { IconUser } from '@douyinfe/semi-icons'; const Logout = function Logout() { return ( - +
+ +
); }; diff --git a/ui/src/components/menu/Menu.jsx b/ui/src/components/menu/Menu.jsx deleted file mode 100644 index 45683ae0..00000000 --- a/ui/src/components/menu/Menu.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Tabs, TabPane } from '@douyinfe/semi-ui'; - -import { useLocation } from 'react-router-dom'; -import { IconUser, IconTerminal, IconSetting, IconArchive } from '@douyinfe/semi-icons'; -import './Menu.less'; - -function parsePathName(name) { - const split = name.split('/').filter((s) => s.length !== 0); - return '/' + split[0]; -} - -const TopMenu = function TopMenu({ isAdmin }) { - const navigate = useNavigate(); - const location = useLocation(); - return ( - navigate(key)}> - - - Jobs - - } - /> - - - Found listings - - } - /> - - {isAdmin && ( - - - User - - } - /> - )} - - {isAdmin && ( - - - Settings - - } - /> - )} - - ); -}; - -export default TopMenu; diff --git a/ui/src/components/menu/Menu.less b/ui/src/components/menu/Menu.less deleted file mode 100644 index 34102907..00000000 --- a/ui/src/components/menu/Menu.less +++ /dev/null @@ -1,3 +0,0 @@ -.menu { - margin-top: 3rem; -} diff --git a/ui/src/components/navigation/Navigate.less b/ui/src/components/navigation/Navigate.less new file mode 100644 index 00000000..394b175a --- /dev/null +++ b/ui/src/components/navigation/Navigate.less @@ -0,0 +1,9 @@ +.navigate { + &__logout_Button { + align-items: center; + justify-content: center; + width: 100%; + display: flex; + + } +} \ No newline at end of file diff --git a/ui/src/components/navigation/Navigation.jsx b/ui/src/components/navigation/Navigation.jsx new file mode 100644 index 00000000..a70a17be --- /dev/null +++ b/ui/src/components/navigation/Navigation.jsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { Nav } from '@douyinfe/semi-ui'; +import { IconUser, IconStar, IconSetting, IconTerminal } from '@douyinfe/semi-icons'; +import logoWhite from '../../assets/logo_white.png'; +import Logout from '../logout/Logout.jsx'; +import { useLocation, useNavigate } from 'react-router-dom'; + +import './Navigate.less'; +import { useScreenWidth } from '../../hooks/screenWidth.js'; + +export default function Navigation({ isAdmin }) { + const navigate = useNavigate(); + const location = useLocation(); + + const width = useScreenWidth(); + const collapsed = width <= 850; + + const items = [ + { itemKey: '/jobs', text: 'Jobs', icon: }, + { itemKey: '/listings', text: 'Found Listings', icon: }, + ]; + + if (isAdmin) { + items.push({ itemKey: '/users', text: 'User Management', icon: }); + items.push({ itemKey: '/generalSettings', text: 'Settings', icon: }); + } + + function parsePathName(name) { + const split = name.split('/').filter((s) => s.length !== 0); + return '/' + split[0]; + } + + return ( +