Update legend

dev
Platon Yasev 3 years ago
parent c2900763c7
commit 9a8dacc38a

@ -1,11 +1,11 @@
const POINT_SIZE = 5; const POINT_SIZE = 5;
const UNMATCH_POINT_SIZE = 3; const UNMATCH_POINT_SIZE = 3;
const INITIAL_COLOR = "#CC2222"; export const INITIAL_COLOR = "#CC2222";
const CANCELLED_COLOR = "#CC2222"; export const CANCELLED_COLOR = "#CC2222";
const APPROVE_COLOR = "#ff7d00"; export const APPROVE_COLOR = "#ff7d00";
const WORKING_COLOR = "#006e01"; export const WORKING_COLOR = "#006e01";
const UNMATCHED_COLOR = "#b4b4b4"; export const UNMATCHED_COLOR = "#b4b4b4";
const DEFAULT_POINT_CONFIG = { const DEFAULT_POINT_CONFIG = {
type: "circle", type: "circle",

@ -22,7 +22,7 @@ export const LayersVisibility = () => {
</Checkbox> </Checkbox>
)} )}
{mode === MODES.APPROVE && ( {mode === MODES.APPROVE_WORKING && (
<> <>
<Checkbox <Checkbox
onChange={() => toggleVisibility(LAYER_IDS.approve)} onChange={() => toggleVisibility(LAYER_IDS.approve)}
@ -40,6 +40,18 @@ export const LayersVisibility = () => {
</> </>
)} )}
{mode === MODES.WORKING && (
<>
<Checkbox
className={"!ml-0"}
onChange={() => toggleVisibility(LAYER_IDS.working)}
checked={isVisible[LAYER_IDS.working]}
>
Работает
</Checkbox>
</>
)}
<Checkbox <Checkbox
className={"!ml-0"} className={"!ml-0"}
onChange={() => toggleVisibility(LAYER_IDS.atd)} onChange={() => toggleVisibility(LAYER_IDS.atd)}

@ -1,13 +1,45 @@
import { useMode } from "../stores/useMode";
import { MODES } from "../config";
import { APPROVE_COLOR, WORKING_COLOR } from "./Layers/layers-config";
import { Title } from "../components/Title"; import { Title } from "../components/Title";
export function Legend() { const LegendPointItem = ({ color, name }) => {
return ( return (
<div className="absolute bottom-[10px] left-[10px] text-xs text-grey z-10"> <div className="flex gap-2 items-center">
<Title <span
text={"Размер кружка пропорционален прогнозному трафику"} className="rounded-xl w-3 h-3 inline-block"
className={"text-center mb-1"} style={{ backgroundColor: color }}
classNameText={"lowercase"}
/> />
<span>{name}</span>
</div>
);
};
export function Legend() {
const { mode } = useMode();
const getContent = () => {
if (mode === MODES.APPROVE_WORKING) {
return (
<>
<Title text={"Статус локации"} className={"text-center"} />
<div className="space-y-2">
<LegendPointItem
name="Согласование-установка"
color={APPROVE_COLOR}
/>
<LegendPointItem name="Работает" color={WORKING_COLOR} />
</div>
</>
);
}
return null;
};
return (
<div className="absolute bottom-[20px] left-[20px] text-xs text-grey z-10 bg-white-background-light rounded-xl p-3">
{getContent()}
</div> </div>
); );
} }

@ -152,7 +152,7 @@ const SingleFeaturePopup = ({ feature }) => {
</div> </div>
{mode === MODES.INITIAL && ( {mode === MODES.INITIAL && (
<Button <Button
type="text" type="primary"
className="mt-2 mx-auto" className="mt-2 mx-auto"
block block
onClick={handleSelect} onClick={handleSelect}
@ -170,7 +170,9 @@ const MultipleFeaturesPopup = ({ features, onSelect }) => {
{features.map((feature) => { {features.map((feature) => {
return ( return (
<Button <Button
type={feature.layer.id === "match-points" ? "primary" : "text"} type={
feature.layer.id === LAYER_IDS["initial-match"] ? "primary" : ""
}
className="flex items-center gap-x-1" className="flex items-center gap-x-1"
block block
onClick={() => onSelect(feature)} onClick={() => onSelect(feature)}

@ -21,13 +21,13 @@ export const DISABLED_FILTER_TEXT =
export const MODES = { export const MODES = {
INITIAL: "INITIAL", INITIAL: "INITIAL",
APPROVE: "APPROVE", APPROVE_WORKING: "APPROVE_WORKING",
WORKING: "WORKING", WORKING: "WORKING",
}; };
export const MODE_TO_STATUS_MAPPER = { export const MODE_TO_STATUS_MAPPER = {
[MODES.INITIAL]: [STATUSES.initial], [MODES.INITIAL]: [STATUSES.initial],
[MODES.APPROVE]: [STATUSES.approve, STATUSES.working], [MODES.APPROVE_WORKING]: [STATUSES.approve, STATUSES.working],
[MODES.WORKING]: [STATUSES.working], [MODES.WORKING]: [STATUSES.working],
}; };
@ -36,7 +36,7 @@ export const MODE_TO_LAYER_VISIBILITY_MAPPER = {
visible: [LAYER_IDS.initial], visible: [LAYER_IDS.initial],
invisible: [LAYER_IDS.approve, LAYER_IDS.working], invisible: [LAYER_IDS.approve, LAYER_IDS.working],
}, },
[MODES.APPROVE]: { [MODES.APPROVE_WORKING]: {
visible: [LAYER_IDS.approve, LAYER_IDS.working], visible: [LAYER_IDS.approve, LAYER_IDS.working],
invisible: [LAYER_IDS.initial], invisible: [LAYER_IDS.initial],
}, },

@ -32,9 +32,9 @@ export const Header = () => {
<GiGlowingArtifact /> <GiGlowingArtifact />
</Button> </Button>
<Button <Button
type={getType(MODES.APPROVE)} type={getType(MODES.APPROVE_WORKING)}
className="flex items-center justify-center p-3" className="flex items-center justify-center p-3"
onClick={() => handleClick(MODES.APPROVE)} onClick={() => handleClick(MODES.APPROVE_WORKING)}
> >
<TbTransform /> <TbTransform />
</Button> </Button>

@ -1,11 +1,14 @@
import { SliderComponent as Slider } from "../../../components/SliderComponent"; import { SliderComponent as Slider } from "../../../components/SliderComponent";
import { useFilters } from "../../../stores/useFilters"; import { INITIAL, useFilters } from "../../../stores/useFilters";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { api } from "../../../api"; import { api } from "../../../api";
import { useEffect } from "react"; import { useEffect } from "react";
export const PredictionSlider = ({ disabled }) => { export const PredictionSlider = ({ disabled }) => {
const { filters, setPrediction } = useFilters(); const {
filters: { prediction },
setPrediction,
} = useFilters();
const { data } = useQuery(["max-min"], async () => { const { data } = useQuery(["max-min"], async () => {
const { data } = await api.get(`/api/placement_points/filters/`); const { data } = await api.get(`/api/placement_points/filters/`);
@ -21,13 +24,18 @@ export const PredictionSlider = ({ disabled }) => {
const min = data.prediction_current[0]; const min = data.prediction_current[0];
const max = data.prediction_current[1]; const max = data.prediction_current[1];
setPrediction([min, max]); if (
prediction[0] === INITIAL.prediction[0] &&
prediction[1] === INITIAL.prediction[1]
) {
setPrediction([min, max]);
}
}, [data]); }, [data]);
return ( return (
<Slider <Slider
title={"Прогнозный трафик"} title={"Прогнозный трафик"}
value={filters.prediction} value={prediction}
onAfterChange={handleAfterChange} onAfterChange={handleAfterChange}
min={data?.prediction_current[0]} min={data?.prediction_current[0]}
max={data?.prediction_current[1]} max={data?.prediction_current[1]}

@ -12,34 +12,29 @@ import { twMerge } from "tailwind-merge";
export const Sidebar = ({ isCollapsed }) => { export const Sidebar = ({ isCollapsed }) => {
const hasManualEdits = useHasManualEdits(); const hasManualEdits = useHasManualEdits();
const { reset: resetSelection } = usePointSelection();
const { mode } = useMode(); const { mode } = useMode();
const { reset: resetSelection } = usePointSelection();
return ( return (
<div <div
className={twMerge( className={twMerge(
"bg-white-background h-screen p-3 overflow-y-auto shrink-0 border-solid border-border border-0 border-r-[1px] flex flex-col transition-all", "h-screen p-3 overflow-y-auto shrink-0 border-solid border-border border-0 border-r-[1px] flex flex-col transition-all",
isCollapsed ? "basis-0 p-0 -translate-x-[320px]" : "basis-[320px] p-3" isCollapsed ? "basis-0 p-0 -translate-x-[320px]" : "basis-[320px] p-3"
)} )}
> >
<Header /> <Header />
<div className="space-y-5 flex flex-col justify-between flex-1"> <div className="space-y-5 flex flex-col justify-between flex-1">
<Filters disabled={hasManualEdits} />
<div> <div>
<Filters disabled={hasManualEdits} />
{mode === MODES.INITIAL && hasManualEdits ? ( {mode === MODES.INITIAL && hasManualEdits ? (
<Button <Button block className={"mt-2"} onClick={resetSelection}>
type="text"
block
className={"mt-2"}
onClick={resetSelection}
>
Отменить ручное редактирование Отменить ручное редактирование
</Button> </Button>
) : null} ) : null}
{mode === MODES.INITIAL && <TakeToWorkButton />}
</div> </div>
<div>{mode === MODES.INITIAL && <TakeToWorkButton />}</div>
</div> </div>
</div> </div>
); );

@ -90,9 +90,7 @@ const Header = ({ selectedIds, onClearSelected }) => {
} }
rightColumn={ rightColumn={
selectedIds.length > 0 && ( selectedIds.length > 0 && (
<Button type="text" onClick={handleClear}> <Button onClick={handleClear}>Очистить все</Button>
Очистить все
</Button>
) )
} }
classes={{ classes={{
@ -115,7 +113,7 @@ export const ApproveAndWorkingTable = ({ fullWidth }) => {
const clearSelected = () => setSelectedIds([]); const clearSelected = () => setSelectedIds([]);
const { data, isInitialLoading } = useQuery( const { data, isInitialLoading } = useQuery(
["approve-working-points", region], ["approve-working-points", page, region],
async () => { async () => {
const params = new URLSearchParams({ const params = new URLSearchParams({
page, page,
@ -124,7 +122,8 @@ export const ApproveAndWorkingTable = ({ fullWidth }) => {
}); });
return await getPoints(params, region); return await getPoints(params, region);
} },
{ keepPreviousData: true }
); );
const { data: mergedData, isClickedPointLoading } = useMergeTableData( const { data: mergedData, isClickedPointLoading } = useMergeTableData(

@ -1,11 +1,4 @@
export const columns = [ export const columns = [
{
title: "Id",
dataIndex: "location_id",
key: "location_id",
width: 50,
ellipsis: true,
},
{ {
title: "Адрес", title: "Адрес",
dataIndex: "address", dataIndex: "address",

@ -72,8 +72,8 @@ export const Table = React.memo(
const geometry = parse(record.geometry); const geometry = parse(record.geometry);
map.flyTo({ map.flyTo({
center: [geometry.coordinates[0], geometry.coordinates[1]], center: [geometry.coordinates[0], geometry.coordinates[1]],
zoom: 15, zoom: 13,
speed: 5, essential: true,
}); });
}, },
}; };

@ -7,7 +7,7 @@ import { WorkingTable } from "./WorkingTable/WorkingTable";
export const TableWrapper = ({ fullWidth }) => { export const TableWrapper = ({ fullWidth }) => {
const { mode } = useMode(); const { mode } = useMode();
if (mode === MODES.APPROVE) { if (mode === MODES.APPROVE_WORKING) {
return <ApproveAndWorkingTable fullWidth={fullWidth} />; return <ApproveAndWorkingTable fullWidth={fullWidth} />;
} }

@ -18,7 +18,7 @@ export const WorkingTable = ({ fullWidth }) => {
} = useFilters(); } = useFilters();
const { data, isInitialLoading } = useQuery( const { data, isInitialLoading } = useQuery(
["working-points", region], ["working-points", page, region],
async () => { async () => {
const params = new URLSearchParams({ const params = new URLSearchParams({
page, page,
@ -27,7 +27,8 @@ export const WorkingTable = ({ fullWidth }) => {
}); });
return await getPoints(params, region); return await getPoints(params, region);
} },
{ keepPreviousData: true }
); );
const { data: mergedData, isClickedPointLoading } = useMergeTableData( const { data: mergedData, isClickedPointLoading } = useMergeTableData(

@ -2,8 +2,8 @@ import { create } from "zustand";
import { immer } from "zustand/middleware/immer"; import { immer } from "zustand/middleware/immer";
import { STATUSES } from "../config"; import { STATUSES } from "../config";
const INITIAL = { export const INITIAL = {
prediction: [200, 299], prediction: [0, 0],
categories: [], categories: [],
region: null, region: null,
status: [STATUSES.initial], status: [STATUSES.initial],

@ -8,6 +8,7 @@ module.exports = {
'primary-light': "#ffe4e4", 'primary-light': "#ffe4e4",
blue: "rgba(167,201,236,0.57)", blue: "rgba(167,201,236,0.57)",
"white-background": "rgba(255, 255, 255, 0.9)", "white-background": "rgba(255, 255, 255, 0.9)",
"white-background-light": "rgba(255, 255, 255, 0.6)",
grey: "rgba(0,0, 0, 0.5)", grey: "rgba(0,0, 0, 0.5)",
"grey-light": "rgba(239,239,239,0.9)", "grey-light": "rgba(239,239,239,0.9)",
border: '#d9d9d9' border: '#d9d9d9'

Loading…
Cancel
Save