mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
UI improvements (#283)
* ui-improvements * improving dashboard and settings * improve job overview * improving job card * improving grid view of listings+ * restructuring settings * next release version
This commit is contained in:
committed by
GitHub
parent
a1289acf15
commit
8c039f0026
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, Col, Row, Toast } from '@douyinfe/semi-ui-19';
|
||||
import { Button, Col, Row, Toast, Typography } from '@douyinfe/semi-ui-19';
|
||||
import {
|
||||
IconTerminal,
|
||||
IconStar,
|
||||
@@ -22,7 +22,6 @@ import KpiCard from '../../components/cards/KpiCard.jsx';
|
||||
import PieChartCard from '../../components/cards/PieChartCard.jsx';
|
||||
|
||||
import './Dashboard.less';
|
||||
import { SegmentPart } from '../../components/segment/SegmentPart.jsx';
|
||||
import { xhrPost } from '../../services/xhr.js';
|
||||
import { format } from '../../services/time/timeService.js';
|
||||
|
||||
@@ -35,129 +34,119 @@ export default function Dashboard() {
|
||||
|
||||
const kpis = dashboard?.kpis || { totalJobs: 0, totalListings: 0, providersUsed: 0 };
|
||||
const pieData = dashboard?.pie || [];
|
||||
const { Text } = Typography;
|
||||
|
||||
return (
|
||||
<div className="dashboard">
|
||||
<Text className="dashboard__section-label">General</Text>
|
||||
<Row gutter={[16, 16]} className="dashboard__row">
|
||||
<Col span={12} xs={24} sm={24} md={24} lg={24} xl={12}>
|
||||
<SegmentPart name="General" Icon={IconTerminal}>
|
||||
<Row gutter={[16, 16]} className="dashboard__row">
|
||||
<Col span={12} xs={24} sm={12} md={12} lg={12} xl={12}>
|
||||
<KpiCard
|
||||
title="Search Interval"
|
||||
value={`${dashboard?.general?.interval} min`}
|
||||
icon={<IconClock />}
|
||||
description="Time interval for job execution"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12} xs={24} sm={12} md={12} lg={12} xl={12}>
|
||||
<KpiCard
|
||||
title="Last Search"
|
||||
valueFontSize="14px"
|
||||
value={
|
||||
dashboard?.general?.lastRun == null || dashboard?.general?.lastRun === 0
|
||||
? '---'
|
||||
: format(dashboard?.general?.lastRun)
|
||||
}
|
||||
icon={<IconDoubleChevronLeft />}
|
||||
description="Last execution timestamp"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12} xs={24} sm={12} md={12} lg={12} xl={12}>
|
||||
<KpiCard
|
||||
title="Next Search"
|
||||
value={
|
||||
dashboard?.general?.nextRun == null || dashboard?.general?.nextRun === 0
|
||||
? '---'
|
||||
: format(dashboard?.general?.nextRun)
|
||||
}
|
||||
valueFontSize="14px"
|
||||
icon={<IconDoubleChevronRight />}
|
||||
description="Next execution timestamp"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12} xs={24} sm={12} md={12} lg={12} xl={12}>
|
||||
<KpiCard title="Search Now" icon={<IconSearch />} description="Run a search now">
|
||||
<Button
|
||||
size="small"
|
||||
style={{ marginTop: '.2rem' }}
|
||||
icon={<IconPlayCircle />}
|
||||
aria-label="Start now"
|
||||
onClick={async () => {
|
||||
try {
|
||||
await xhrPost('/api/jobs/startAll', null);
|
||||
Toast.success('Successfully triggered Fredy search.');
|
||||
} catch {
|
||||
Toast.error('Failed to trigger search');
|
||||
}
|
||||
}}
|
||||
>
|
||||
Search now
|
||||
</Button>
|
||||
</KpiCard>
|
||||
</Col>
|
||||
</Row>
|
||||
</SegmentPart>
|
||||
<Col xs={24} sm={12} md={12} lg={6} xl={6}>
|
||||
<KpiCard
|
||||
title="Search Interval"
|
||||
value={`${dashboard?.general?.interval} min`}
|
||||
icon={<IconClock />}
|
||||
description="Time interval for job execution"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12} xs={24} sm={24} md={24} lg={24} xl={12}>
|
||||
<SegmentPart name="Overview" Icon={IconStar}>
|
||||
<Row gutter={[16, 16]} className="dashboard__row">
|
||||
<Col span={12} xs={24} sm={12} md={12} lg={12} xl={12}>
|
||||
<KpiCard
|
||||
title="Jobs"
|
||||
color="blue"
|
||||
value={!kpis.totalJobs ? '---' : kpis.totalJobs}
|
||||
icon={<IconTerminal />}
|
||||
description="Total number of jobs"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12} xs={24} sm={12} md={12} lg={12} xl={12}>
|
||||
<KpiCard
|
||||
title="Listings"
|
||||
color="orange"
|
||||
value={!kpis.totalListings ? '---' : kpis.totalListings}
|
||||
icon={<IconStarStroked />}
|
||||
description="Total listings found"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12} xs={24} sm={12} md={12} lg={12} xl={12}>
|
||||
<KpiCard
|
||||
title="Active Listings"
|
||||
color="green"
|
||||
value={!kpis.numberOfActiveListings ? '---' : kpis.numberOfActiveListings}
|
||||
icon={<IconStar />}
|
||||
description="Total active listings"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12} xs={24} sm={12} md={12} lg={12} xl={12}>
|
||||
<KpiCard
|
||||
title="Avg. Price"
|
||||
color="purple"
|
||||
value={`${
|
||||
!kpis.avgPriceOfListings
|
||||
? '---'
|
||||
: new Intl.NumberFormat('de-DE', {
|
||||
style: 'currency',
|
||||
currency: 'EUR',
|
||||
}).format(kpis.avgPriceOfListings)
|
||||
}`}
|
||||
icon={<IconNoteMoney />}
|
||||
description="Avg. Price of listings"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</SegmentPart>
|
||||
<Col xs={24} sm={12} md={12} lg={6} xl={6}>
|
||||
<KpiCard
|
||||
title="Last Search"
|
||||
valueFontSize="14px"
|
||||
value={
|
||||
dashboard?.general?.lastRun == null || dashboard?.general?.lastRun === 0
|
||||
? '---'
|
||||
: format(dashboard?.general?.lastRun)
|
||||
}
|
||||
icon={<IconDoubleChevronLeft />}
|
||||
description="Last execution timestamp"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={12} lg={6} xl={6}>
|
||||
<KpiCard
|
||||
title="Next Search"
|
||||
value={
|
||||
dashboard?.general?.nextRun == null || dashboard?.general?.nextRun === 0
|
||||
? '---'
|
||||
: format(dashboard?.general?.nextRun)
|
||||
}
|
||||
valueFontSize="14px"
|
||||
icon={<IconDoubleChevronRight />}
|
||||
description="Next execution timestamp"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={12} lg={6} xl={6}>
|
||||
<KpiCard title="Search Now" icon={<IconSearch />} description="Run a search now">
|
||||
<Button
|
||||
size="small"
|
||||
style={{ marginTop: '.2rem' }}
|
||||
icon={<IconPlayCircle />}
|
||||
aria-label="Start now"
|
||||
onClick={async () => {
|
||||
try {
|
||||
await xhrPost('/api/jobs/startAll', null);
|
||||
Toast.success('Successfully triggered Fredy search.');
|
||||
} catch {
|
||||
Toast.error('Failed to trigger search');
|
||||
}
|
||||
}}
|
||||
>
|
||||
Search now
|
||||
</Button>
|
||||
</KpiCard>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<SegmentPart
|
||||
name="Provider Insights"
|
||||
Icon={IconStar}
|
||||
helpText="Percentage of found listings over all providers"
|
||||
className="dashboard__provider-insights"
|
||||
>
|
||||
<Text className="dashboard__section-label">Overview</Text>
|
||||
<Row gutter={[16, 16]} className="dashboard__row">
|
||||
<Col xs={24} sm={12} md={12} lg={6} xl={6}>
|
||||
<KpiCard
|
||||
title="Jobs"
|
||||
color="blue"
|
||||
value={!kpis.totalJobs ? '---' : kpis.totalJobs}
|
||||
icon={<IconTerminal />}
|
||||
description="Total number of jobs"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={12} lg={6} xl={6}>
|
||||
<KpiCard
|
||||
title="Listings"
|
||||
color="orange"
|
||||
value={!kpis.totalListings ? '---' : kpis.totalListings}
|
||||
icon={<IconStarStroked />}
|
||||
description="Total listings found"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={12} lg={6} xl={6}>
|
||||
<KpiCard
|
||||
title="Active Listings"
|
||||
color="green"
|
||||
value={!kpis.numberOfActiveListings ? '---' : kpis.numberOfActiveListings}
|
||||
icon={<IconStar />}
|
||||
description="Total active listings"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={12} lg={6} xl={6}>
|
||||
<KpiCard
|
||||
title="Avg. Price"
|
||||
color="purple"
|
||||
value={`${
|
||||
!kpis.avgPriceOfListings
|
||||
? '---'
|
||||
: new Intl.NumberFormat('de-DE', {
|
||||
style: 'currency',
|
||||
currency: 'EUR',
|
||||
}).format(kpis.avgPriceOfListings)
|
||||
}`}
|
||||
icon={<IconNoteMoney />}
|
||||
description="Avg. Price of listings"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Text className="dashboard__section-label">Provider Insights</Text>
|
||||
<div className="dashboard__pie-wrapper">
|
||||
<PieChartCard data={pieData} />
|
||||
</SegmentPart>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,31 +3,32 @@
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
|
||||
&__row {
|
||||
margin-bottom: 24px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.semi-col {
|
||||
margin-bottom: 0; // Handled by Row gutter
|
||||
}
|
||||
&__section-label {
|
||||
display: block;
|
||||
font-size: 11px !important;
|
||||
font-weight: 600 !important;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: #5a6478 !important;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
&__provider-insights {
|
||||
&__row {
|
||||
margin-bottom: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
&__pie-wrapper {
|
||||
background: #23242a;
|
||||
border: 1px solid #37404e;
|
||||
|
||||
border-radius: 10px;
|
||||
padding: 24px;
|
||||
max-height: 320px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 !important;
|
||||
|
||||
.semi-card-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
max-height: 300px;
|
||||
|
||||
> * {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user