refine Semi UI mileage filters
This commit is contained in:
@@ -279,6 +279,7 @@ test('uses a compact bottom sheet for mileage source strategy on mobile', async
|
|||||||
prepareData();
|
prepareData();
|
||||||
renderPage('/statistics?vins=LTEST000000000001&dateFrom=2026-07-13&dateTo=2026-07-14');
|
renderPage('/statistics?vins=LTEST000000000001&dateFrom=2026-07-13&dateTo=2026-07-14');
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /修改里程范围/ }));
|
||||||
fireEvent.click(screen.getByRole('button', { name: /数据源/ }));
|
fireEvent.click(screen.getByRole('button', { name: /数据源/ }));
|
||||||
|
|
||||||
expect(screen.getByRole('dialog', { name: '数据源策略配置' })).toBeInTheDocument();
|
expect(screen.getByRole('dialog', { name: '数据源策略配置' })).toBeInTheDocument();
|
||||||
@@ -286,6 +287,33 @@ test('uses a compact bottom sheet for mileage source strategy on mobile', async
|
|||||||
expect(document.querySelector('.v2-mileage-source-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(58dvh, 500px)' });
|
expect(document.querySelector('.v2-mileage-source-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(58dvh, 500px)' });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('opens mobile mileage filters in a bottom task sheet without displacing the data canvas', async () => {
|
||||||
|
layout.mobile = true;
|
||||||
|
prepareData();
|
||||||
|
const view = renderPage('/statistics?vins=LTEST000000000001&dateFrom=2026-07-13&dateTo=2026-07-14');
|
||||||
|
|
||||||
|
expect(await screen.findByText('车辆每日里程')).toBeInTheDocument();
|
||||||
|
expect(view.container.querySelector('.v2-mileage-mobile-discovery')).toBeInTheDocument();
|
||||||
|
expect(view.container.querySelector('.v2-mileage-query-panel')).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('dialog', { name: '里程范围筛选' })).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('textbox', { name: '搜索车牌' })).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /修改里程范围/ }));
|
||||||
|
|
||||||
|
expect(await screen.findByRole('dialog', { name: '里程范围筛选' })).toBeInTheDocument();
|
||||||
|
expect(document.querySelector('.v2-mileage-filter-sidesheet')).toHaveClass('semi-sidesheet-bottom');
|
||||||
|
expect(document.querySelector('.v2-mileage-filter-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(82dvh, 690px)' });
|
||||||
|
expect(screen.getByRole('textbox', { name: '搜索车牌' })).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: '应用并查询' })).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: '关闭里程范围筛选' })).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: '关闭里程范围筛选' }));
|
||||||
|
|
||||||
|
expect(screen.getByRole('dialog', { name: '里程范围筛选' })).toHaveClass('semi-sidesheet-animation-content_hide_bottom');
|
||||||
|
expect(screen.getByText('车辆每日里程')).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('button', { name: /修改里程范围/ })).toHaveAttribute('aria-expanded', 'false');
|
||||||
|
});
|
||||||
|
|
||||||
test('paginates all unique vehicles when no license plate is selected', async () => {
|
test('paginates all unique vehicles when no license plate is selected', async () => {
|
||||||
prepareData();
|
prepareData();
|
||||||
const firstPage = Array.from({ length: 20 }, (_, index) => ({ vin: `VIN${String(index + 1).padStart(14, '0')}`, plate: `粤A${String(index + 1).padStart(5, '0')}` }));
|
const firstPage = Array.from({ length: 20 }, (_, index) => ({ vin: `VIN${String(index + 1).padStart(14, '0')}`, plate: `粤A${String(index + 1).padStart(5, '0')}` }));
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { createMileageExportStream, type MileageExportStream } from '../domain/m
|
|||||||
import { formatZhNumber } from '../domain/formatters';
|
import { formatZhNumber } from '../domain/formatters';
|
||||||
import { InlineError, PanelEmpty, PanelLoading } from '../shared/AsyncState';
|
import { InlineError, PanelEmpty, PanelLoading } from '../shared/AsyncState';
|
||||||
import { MonitorReturnBar } from '../shared/MonitorReturnBar';
|
import { MonitorReturnBar } from '../shared/MonitorReturnBar';
|
||||||
|
import { MobileFilterToggle } from '../shared/MobileFilterToggle';
|
||||||
import { TablePagination } from '../shared/TablePagination';
|
import { TablePagination } from '../shared/TablePagination';
|
||||||
import { VehicleCandidateList } from '../shared/VehicleCandidateList';
|
import { VehicleCandidateList } from '../shared/VehicleCandidateList';
|
||||||
import { mergeVehicleCandidates } from '../shared/vehicleCandidates';
|
import { mergeVehicleCandidates } from '../shared/vehicleCandidates';
|
||||||
@@ -354,6 +355,7 @@ const MileageTable = memo(function MileageTable({ rows, dates, scrollRef }: { ro
|
|||||||
export default function StatisticsPage() {
|
export default function StatisticsPage() {
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
const monitorReturn = monitorReturnFromParams(searchParams);
|
const monitorReturn = monitorReturnFromParams(searchParams);
|
||||||
|
const mobileLayout = useMobileLayout();
|
||||||
const [draft, setDraft] = useState<Criteria>(() => initialCriteria(searchParams));
|
const [draft, setDraft] = useState<Criteria>(() => initialCriteria(searchParams));
|
||||||
const [criteria, setCriteria] = useState<Criteria>(() => initialCriteria(searchParams));
|
const [criteria, setCriteria] = useState<Criteria>(() => initialCriteria(searchParams));
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
@@ -362,10 +364,12 @@ export default function StatisticsPage() {
|
|||||||
const [exportProgress, setExportProgress] = useState<ExportProgress>();
|
const [exportProgress, setExportProgress] = useState<ExportProgress>();
|
||||||
const [validationError, setValidationError] = useState('');
|
const [validationError, setValidationError] = useState('');
|
||||||
const [filtersCollapsed, setFiltersCollapsed] = useState(true);
|
const [filtersCollapsed, setFiltersCollapsed] = useState(true);
|
||||||
|
const mobileFiltersOpen = mobileLayout && !filtersCollapsed;
|
||||||
const exportControllerRef = useRef<AbortController | null>(null);
|
const exportControllerRef = useRef<AbortController | null>(null);
|
||||||
const pageRef = useRef<HTMLDivElement>(null);
|
const pageRef = useRef<HTMLDivElement>(null);
|
||||||
const tableScrollRef = useRef<HTMLDivElement>(null);
|
const tableScrollRef = useRef<HTMLDivElement>(null);
|
||||||
const mountedRef = useRef(true);
|
const mountedRef = useRef(true);
|
||||||
|
useSideSheetA11y(mobileFiltersOpen, '.v2-mileage-filter-sidesheet', 'v2-mileage-filter-panel', '里程范围筛选', '关闭里程范围筛选');
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
mountedRef.current = true;
|
mountedRef.current = true;
|
||||||
return () => {
|
return () => {
|
||||||
@@ -435,14 +439,32 @@ export default function StatisticsPage() {
|
|||||||
}), [displayVehicles, mileageByVin, rankingByVin]);
|
}), [displayVehicles, mileageByVin, rankingByVin]);
|
||||||
const totalVehicles = hasVehicles ? criteria.vehicles.length : fleetVehicles.data?.total ?? 0;
|
const totalVehicles = hasVehicles ? criteria.vehicles.length : fleetVehicles.data?.total ?? 0;
|
||||||
const totalPages = Math.max(1, Math.ceil(totalVehicles / PAGE_SIZE));
|
const totalPages = Math.max(1, Math.ceil(totalVehicles / PAGE_SIZE));
|
||||||
const submit = (event: FormEvent) => {
|
const applyDraft = () => {
|
||||||
event.preventDefault();
|
|
||||||
const error = mileageDateRangeError(draft);
|
const error = mileageDateRangeError(draft);
|
||||||
setValidationError(error);
|
setValidationError(error);
|
||||||
if (error) return;
|
if (error) return;
|
||||||
setPage(1); setExportFeedback(''); setCriteria(draft); setSearchParams(preserveMonitorReturn(mileageParams(draft, -1), monitorReturn), { replace: true }); setFiltersCollapsed(true);
|
setPage(1); setExportFeedback(''); setCriteria(draft); setSearchParams(preserveMonitorReturn(mileageParams(draft, -1), monitorReturn), { replace: true }); setFiltersCollapsed(true);
|
||||||
};
|
};
|
||||||
const setRange = (range: { dateFrom: string; dateTo: string }) => { const next = { ...draft, ...range }; setPage(1); setExportFeedback(''); setValidationError(''); setDraft(next); setCriteria(next); setSearchParams(preserveMonitorReturn(mileageParams(next, -1), monitorReturn), { replace: true }); };
|
const submit = (event: FormEvent) => { event.preventDefault(); applyDraft(); };
|
||||||
|
const setRange = (range: { dateFrom: string; dateTo: string }) => { const next = { ...draft, ...range }; setPage(1); setExportFeedback(''); setValidationError(''); setDraft(next); setCriteria(next); setSearchParams(preserveMonitorReturn(mileageParams(next, -1), monitorReturn), { replace: true }); setFiltersCollapsed(true); };
|
||||||
|
const closeMobileFilters = () => {
|
||||||
|
setDraft(criteria);
|
||||||
|
setValidationError('');
|
||||||
|
setFiltersCollapsed(true);
|
||||||
|
};
|
||||||
|
const toggleFilters = () => {
|
||||||
|
if (!mobileLayout) {
|
||||||
|
setFiltersCollapsed((value) => !value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mobileFiltersOpen) {
|
||||||
|
closeMobileFilters();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setDraft(criteria);
|
||||||
|
setValidationError('');
|
||||||
|
setFiltersCollapsed(false);
|
||||||
|
};
|
||||||
const todayRange = defaultWindow(1);
|
const todayRange = defaultWindow(1);
|
||||||
const yesterdayRange = defaultWindow(1, 1);
|
const yesterdayRange = defaultWindow(1, 1);
|
||||||
const sevenDayRange = defaultWindow(7);
|
const sevenDayRange = defaultWindow(7);
|
||||||
@@ -533,6 +555,17 @@ export default function StatisticsPage() {
|
|||||||
exportControllerRef.current.abort();
|
exportControllerRef.current.abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rangeSummary = criteria.vehicles.length ? `已选 ${criteria.vehicles.length} 辆 · ${inclusiveDays(criteria.dateFrom, criteria.dateTo)} 天` : `全部车辆 · ${inclusiveDays(criteria.dateFrom, criteria.dateTo)} 天`;
|
||||||
|
const filterForm = <form className="v2-mileage-filter" onSubmit={submit}>
|
||||||
|
<VehicleMultiSelect value={draft.vehicles} onChange={(vehicles) => setDraft((current) => ({ ...current, vehicles }))} />
|
||||||
|
<label><span>开始日期</span><Input aria-label="开始日期" type="date" value={draft.dateFrom} max={draft.dateTo} onChange={(value) => setDraft((current) => ({ ...current, dateFrom: value }))} /></label>
|
||||||
|
<label><span>结束日期</span><Input aria-label="结束日期" type="date" value={draft.dateTo} min={draft.dateFrom} onChange={(value) => setDraft((current) => ({ ...current, dateTo: value }))} /></label>
|
||||||
|
<Button className="v2-primary-button v2-mileage-inline-submit" theme="solid" htmlType="submit">查询</Button>
|
||||||
|
<SourceStrategy value={draft.sources} onChange={(sources) => setDraft((current) => ({ ...current, sources }))} />
|
||||||
|
<div className="v2-mileage-ranges"><span>快捷范围</span><Button theme={isSameRange(draft, todayRange) ? 'solid' : 'light'} onClick={() => setRange(todayRange)}>今天</Button><Button theme={isSameRange(draft, yesterdayRange) ? 'solid' : 'light'} onClick={() => setRange(yesterdayRange)}>昨天</Button><Button theme={isSameRange(draft, sevenDayRange) ? 'solid' : 'light'} onClick={() => setRange(sevenDayRange)}>近 7 天</Button><Button theme={isSameRange(draft, thirtyDayRange) ? 'solid' : 'light'} onClick={() => setRange(thirtyDayRange)}>近 30 天</Button><Button theme={isSameRange(draft, ninetyDayRange) ? 'solid' : 'light'} onClick={() => setRange(ninetyDayRange)}>近 90 天</Button></div>
|
||||||
|
</form>;
|
||||||
|
const filterValidation = validationError || criteriaError ? <p className="v2-mileage-validation" role="alert">{validationError || criteriaError}</p> : null;
|
||||||
|
|
||||||
return <div className="v2-mileage-page" ref={pageRef}>
|
return <div className="v2-mileage-page" ref={pageRef}>
|
||||||
<MonitorReturnBar />
|
<MonitorReturnBar />
|
||||||
<div className="v2-mileage-discovery-shell">
|
<div className="v2-mileage-discovery-shell">
|
||||||
@@ -545,28 +578,44 @@ export default function StatisticsPage() {
|
|||||||
statusColor={criteria.vehicles.length ? 'blue' : 'grey'}
|
statusColor={criteria.vehicles.length ? 'blue' : 'grey'}
|
||||||
meta={<span>{criteria.sources.find((source) => source.enabled)?.protocol ?? '未配置'} 优先</span>}
|
meta={<span>{criteria.sources.find((source) => source.enabled)?.protocol ?? '未配置'} 优先</span>}
|
||||||
/>
|
/>
|
||||||
<WorkspaceFilterPanel
|
{mobileLayout ? <div className="v2-mileage-mobile-discovery">
|
||||||
|
<MobileFilterToggle
|
||||||
|
title="里程范围"
|
||||||
|
summary={rangeSummary}
|
||||||
|
expanded={mobileFiltersOpen}
|
||||||
|
expandedLabel="关闭"
|
||||||
|
collapsedLabel="修改"
|
||||||
|
onToggle={toggleFilters}
|
||||||
|
/>
|
||||||
|
<SummaryRail data={statistics.data} criteria={criteria} fleetTotal={fleetVehicles.data?.total} loading={statistics.isLoading} />
|
||||||
|
<SideSheet
|
||||||
|
className="v2-mileage-filter-sidesheet"
|
||||||
|
visible={mobileFiltersOpen}
|
||||||
|
placement="bottom"
|
||||||
|
height="min(82dvh, 690px)"
|
||||||
|
aria-label="里程范围筛选"
|
||||||
|
title={<div className="v2-mileage-filter-title"><strong>里程范围</strong><span>选择车辆、自然日与数据源</span></div>}
|
||||||
|
onCancel={closeMobileFilters}
|
||||||
|
footer={<div className="v2-mileage-filter-footer"><span>应用后刷新里程统计与车辆矩阵</span><Button theme="solid" onClick={applyDraft}>应用并查询</Button></div>}
|
||||||
|
>
|
||||||
|
{filterForm}
|
||||||
|
{filterValidation}
|
||||||
|
</SideSheet>
|
||||||
|
</div> : <WorkspaceFilterPanel
|
||||||
className="v2-mileage-query-panel"
|
className="v2-mileage-query-panel"
|
||||||
title="里程范围"
|
title="里程范围"
|
||||||
description="车牌、自然日与里程数据源策略"
|
description="车牌、自然日与里程数据源策略"
|
||||||
mobileSummary={criteria.vehicles.length ? `已选 ${criteria.vehicles.length} 辆 · ${inclusiveDays(criteria.dateFrom, criteria.dateTo)} 天` : `全部车辆 · ${inclusiveDays(criteria.dateFrom, criteria.dateTo)} 天`}
|
mobileSummary={rangeSummary}
|
||||||
expanded={!filtersCollapsed}
|
expanded={!filtersCollapsed}
|
||||||
status={`${criteria.vehicles.length ? `${criteria.vehicles.length} 辆` : '全部授权车辆'} · ${inclusiveDays(criteria.dateFrom, criteria.dateTo)} 天`}
|
status={`${criteria.vehicles.length ? `${criteria.vehicles.length} 辆` : '全部授权车辆'} · ${inclusiveDays(criteria.dateFrom, criteria.dateTo)} 天`}
|
||||||
statusColor={criteria.vehicles.length ? 'blue' : 'grey'}
|
statusColor={criteria.vehicles.length ? 'blue' : 'grey'}
|
||||||
collapsedLabel="修改"
|
collapsedLabel="修改"
|
||||||
onToggle={() => setFiltersCollapsed((value) => !value)}
|
onToggle={toggleFilters}
|
||||||
>
|
>
|
||||||
<form className={`v2-mileage-filter${filtersCollapsed ? ' is-mobile-collapsed' : ''}`} onSubmit={submit}>
|
{filterForm}
|
||||||
<VehicleMultiSelect value={draft.vehicles} onChange={(vehicles) => setDraft((current) => ({ ...current, vehicles }))} />
|
{filterValidation}
|
||||||
<label><span>开始日期</span><Input aria-label="开始日期" type="date" value={draft.dateFrom} max={draft.dateTo} onChange={(value) => setDraft((current) => ({ ...current, dateFrom: value }))} /></label>
|
|
||||||
<label><span>结束日期</span><Input aria-label="结束日期" type="date" value={draft.dateTo} min={draft.dateFrom} onChange={(value) => setDraft((current) => ({ ...current, dateTo: value }))} /></label>
|
|
||||||
<Button className="v2-primary-button" theme="solid" htmlType="submit">查询</Button>
|
|
||||||
<SourceStrategy value={draft.sources} onChange={(sources) => setDraft((current) => ({ ...current, sources }))} />
|
|
||||||
<div className="v2-mileage-ranges"><span>快捷范围</span><Button theme={isSameRange(draft, todayRange) ? 'solid' : 'light'} onClick={() => setRange(todayRange)}>今天</Button><Button theme={isSameRange(draft, yesterdayRange) ? 'solid' : 'light'} onClick={() => setRange(yesterdayRange)}>昨天</Button><Button theme={isSameRange(draft, sevenDayRange) ? 'solid' : 'light'} onClick={() => setRange(sevenDayRange)}>近 7 天</Button><Button theme={isSameRange(draft, thirtyDayRange) ? 'solid' : 'light'} onClick={() => setRange(thirtyDayRange)}>近 30 天</Button><Button theme={isSameRange(draft, ninetyDayRange) ? 'solid' : 'light'} onClick={() => setRange(ninetyDayRange)}>近 90 天</Button></div>
|
|
||||||
</form>
|
|
||||||
{validationError || criteriaError ? <p className="v2-mileage-validation" role="alert">{validationError || criteriaError}</p> : null}
|
|
||||||
<SummaryRail data={statistics.data} criteria={criteria} fleetTotal={fleetVehicles.data?.total} loading={statistics.isLoading} />
|
<SummaryRail data={statistics.data} criteria={criteria} fleetTotal={fleetVehicles.data?.total} loading={statistics.isLoading} />
|
||||||
</WorkspaceFilterPanel>
|
</WorkspaceFilterPanel>}
|
||||||
</div>
|
</div>
|
||||||
{statistics.isError || mileage.isError || fleetVehicles.isError ? <InlineError message={(statistics.error ?? mileage.error ?? fleetVehicles.error) instanceof Error ? (statistics.error ?? mileage.error ?? fleetVehicles.error as Error).message : '里程数据加载失败'} onRetry={() => { statistics.refetch(); mileage.refetch(); if (!hasVehicles) fleetVehicles.refetch(); }} /> : null}
|
{statistics.isError || mileage.isError || fleetVehicles.isError ? <InlineError message={(statistics.error ?? mileage.error ?? fleetVehicles.error) instanceof Error ? (statistics.error ?? mileage.error ?? fleetVehicles.error as Error).message : '里程数据加载失败'} onRetry={() => { statistics.refetch(); mileage.refetch(); if (!hasVehicles) fleetVehicles.refetch(); }} /> : null}
|
||||||
<Card className="v2-mileage-results" bodyStyle={{ padding: 0 }}>
|
<Card className="v2-mileage-results" bodyStyle={{ padding: 0 }}>
|
||||||
|
|||||||
@@ -365,6 +365,9 @@ describe('V2 production entry', () => {
|
|||||||
expect(corePageSources.StatisticsPage).toContain('<Tag');
|
expect(corePageSources.StatisticsPage).toContain('<Tag');
|
||||||
expect(corePageSources.StatisticsPage).toContain('<SideSheet');
|
expect(corePageSources.StatisticsPage).toContain('<SideSheet');
|
||||||
expect(corePageSources.StatisticsPage).toContain('v2-mileage-source-sidesheet');
|
expect(corePageSources.StatisticsPage).toContain('v2-mileage-source-sidesheet');
|
||||||
|
expect(corePageSources.StatisticsPage).toContain('className="v2-mileage-filter-sidesheet"');
|
||||||
|
expect(corePageSources.StatisticsPage).toContain('<MobileFilterToggle');
|
||||||
|
expect(corePageSources.StatisticsPage).toContain('placement="bottom"');
|
||||||
expect(corePageSources.StatisticsPage).not.toContain('v2-mileage-source-popover');
|
expect(corePageSources.StatisticsPage).not.toContain('v2-mileage-source-popover');
|
||||||
expect(corePageSources.StatisticsPage).toContain('<Table className="v2-mileage-table"');
|
expect(corePageSources.StatisticsPage).toContain('<Table className="v2-mileage-table"');
|
||||||
expect(v2Styles).toContain('.v2-mileage-table.semi-table-wrapper :is(.semi-table-row-head,.semi-table-row-cell).is-plate');
|
expect(v2Styles).toContain('.v2-mileage-table.semi-table-wrapper :is(.semi-table-row-head,.semi-table-row-cell).is-plate');
|
||||||
|
|||||||
@@ -11563,3 +11563,128 @@ button, a { -webkit-tap-highlight-color: transparent; }
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Semi UI mileage workflow: keep the mobile data canvas stable while filters open. */
|
||||||
|
.v2-mileage-filter-title {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-title strong {
|
||||||
|
color: #213149;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-title span {
|
||||||
|
color: #7c8b9f;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-footer {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-footer > span {
|
||||||
|
color: #7b899b;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-footer > .semi-button {
|
||||||
|
min-width: 118px;
|
||||||
|
min-height: 38px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
.v2-mileage-mobile-discovery {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
gap: 7px;
|
||||||
|
}
|
||||||
|
.v2-mileage-mobile-discovery > .v2-mobile-filter-toggle.semi-button {
|
||||||
|
min-height: 58px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .semi-sidesheet-inner {
|
||||||
|
width: 100vw !important;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 18px 18px 0 0;
|
||||||
|
background: #f4f7fb;
|
||||||
|
box-shadow: 0 -20px 56px rgba(25, 45, 72, .2);
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .semi-sidesheet-header {
|
||||||
|
min-height: 68px;
|
||||||
|
border-bottom: 1px solid #dfe7f0;
|
||||||
|
background: rgba(255, 255, 255, .98);
|
||||||
|
padding: 11px 14px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .semi-sidesheet-body {
|
||||||
|
overflow: auto;
|
||||||
|
background: #f4f7fb;
|
||||||
|
padding: 12px;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .semi-sidesheet-footer {
|
||||||
|
border-top: 1px solid #dfe7f0;
|
||||||
|
background: rgba(255, 255, 255, .98);
|
||||||
|
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-filter {
|
||||||
|
display: grid !important;
|
||||||
|
min-height: 0;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 12px;
|
||||||
|
border: 1px solid #dfe7f0;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 12px;
|
||||||
|
box-shadow: 0 8px 24px rgba(31, 53, 80, .06);
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-filter > label {
|
||||||
|
gap: 6px;
|
||||||
|
color: #5f7188;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-filter > label > .semi-input-wrapper,
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-source-trigger.semi-button {
|
||||||
|
height: 44px;
|
||||||
|
min-height: 44px;
|
||||||
|
border-radius: 9px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-selection > .semi-input-wrapper .semi-input,
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-filter > label > .semi-input-wrapper .semi-input {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-inline-submit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-source-strategy {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-ranges {
|
||||||
|
height: 44px;
|
||||||
|
order: 5;
|
||||||
|
border: 1px solid #e0e7f0;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: #f4f7fb;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-ranges .semi-button {
|
||||||
|
height: 34px;
|
||||||
|
border-radius: 7px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-sidesheet .v2-mileage-validation {
|
||||||
|
margin: 9px 2px 0;
|
||||||
|
}
|
||||||
|
.v2-mileage-filter-footer > span {
|
||||||
|
max-width: 150px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user