feat: update demo page + add city_id for media and articles
This commit is contained in:
@@ -286,9 +286,9 @@ export const RouteCreatePage = observer(() => {
|
||||
newRoute.governor_appeal = governor_appeal;
|
||||
}
|
||||
|
||||
await routeStore.createRoute(newRoute);
|
||||
const newId = await routeStore.createRoute(newRoute);
|
||||
toast.success("Маршрут успешно создан");
|
||||
navigate(-1);
|
||||
navigate(`/route/${newId}/edit`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Произошла ошибка при создании маршрута");
|
||||
|
||||
@@ -141,6 +141,7 @@ export function RightSidebar() {
|
||||
bgcolor="primary.main"
|
||||
border="1px solid #e0e0e0"
|
||||
borderRadius={2}
|
||||
zIndex={2}
|
||||
>
|
||||
<Typography variant="h6" sx={{ mb: 2, color: "#fff" }} textAlign="center">
|
||||
Настройка маршрута
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Stack, Typography, Box, IconButton } from "@mui/material";
|
||||
import { Close } from "@mui/icons-material";
|
||||
import { Landmark } from "lucide-react";
|
||||
import { useMapData } from "./MapDataContext";
|
||||
import { RouteWidget } from "./webgl-prototype/RouteWidget";
|
||||
|
||||
export function Widgets() {
|
||||
const { selectedSight, setSelectedSight } = useMapData();
|
||||
@@ -13,22 +14,11 @@ export function Widgets() {
|
||||
position="absolute"
|
||||
top={32}
|
||||
left={32}
|
||||
zIndex={2}
|
||||
sx={{ pointerEvents: "none" }}
|
||||
>
|
||||
<Stack
|
||||
bgcolor="primary.main"
|
||||
width={361}
|
||||
height={96}
|
||||
p={2}
|
||||
m={2}
|
||||
borderRadius={2}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Typography variant="h6" sx={{ color: "#fff" }}>
|
||||
Остановка
|
||||
</Typography>
|
||||
</Stack>
|
||||
{/* Виджет маршрута */}
|
||||
<RouteWidget />
|
||||
|
||||
{/* Виджет выбранной достопримечательности (заменяет виджет погоды) */}
|
||||
<Stack
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
.route-widget-label.marquee {
|
||||
display: inline-block;
|
||||
animation: marquee 14s linear infinite;
|
||||
}
|
||||
|
||||
.route-widget-subtitle.marquee {
|
||||
display: inline-block;
|
||||
animation: marquee 14s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes marquee {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.route-widget {
|
||||
width: 361px;
|
||||
height: 96px;
|
||||
position: fixed;
|
||||
display: inline-flex;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3) inset,
|
||||
/* Внутренняя рамка */ 4px 4px 12px 0 rgba(255, 255, 255, 0.12) inset; /* Ваш существующий внутренний shadow */
|
||||
padding: 1px; /* Чтобы контент не прилипал к рамке */
|
||||
background: linear-gradient(
|
||||
to bottom right,
|
||||
rgba(255, 255, 255, 0.2) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
),
|
||||
rgba(179, 165, 152, 0.4);
|
||||
backdrop-filter: blur(10px);
|
||||
pointer-events: auto;
|
||||
z-index: 10000001;
|
||||
}
|
||||
|
||||
.route-widget-number {
|
||||
position: absolute;
|
||||
width: fit-content;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
min-width: 94px;
|
||||
max-width: 100px;
|
||||
height: 96px;
|
||||
background-color: #fcd500;
|
||||
color: black;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 70px;
|
||||
padding: 14px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.route-widget-content {
|
||||
overflow: hidden;
|
||||
width: 257px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 13px;
|
||||
margin-left: 109px;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
.route-widget-label {
|
||||
white-space: nowrap;
|
||||
font-size: 24px;
|
||||
margin: 1px 0;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 24px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.route-widget-label--medium {
|
||||
font-size: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.route-widget-label--small {
|
||||
font-size: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.route-widget-label--xsmall {
|
||||
font-size: 18px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.route-widget-subtitle {
|
||||
white-space: nowrap;
|
||||
color: #cbcbcb;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
margin-top: 4px;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import styles from "./RouteWidget.module.css";
|
||||
import { useMapData } from "../MapDataContext";
|
||||
import { languageStore } from "@shared";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
const shouldAnimate = (text: string | undefined, maxLength: number) =>
|
||||
(text?.length ?? 0) > maxLength;
|
||||
|
||||
const getLabelSizeClass = (text: string | undefined) => {
|
||||
const length = text?.length ?? 0;
|
||||
if (length <= 40) return "";
|
||||
if (length <= 60) return styles["route-widget-label--medium"];
|
||||
if (length <= 80) return styles["route-widget-label--small"];
|
||||
return styles["route-widget-label--xsmall"];
|
||||
};
|
||||
|
||||
export const RouteWidget = observer(() => {
|
||||
const { routeData, stationData } = useMapData();
|
||||
const { language } = languageStore;
|
||||
|
||||
const stations = stationData?.[language] ?? stationData?.["ru"] ?? [];
|
||||
const stationsRu = stationData?.["ru"] ?? [];
|
||||
|
||||
const startStation = stations[0];
|
||||
const endStation = stations[stations.length - 1];
|
||||
|
||||
const startStationRu = stationsRu[0];
|
||||
const endStationRu = stationsRu[stationsRu.length - 1];
|
||||
|
||||
const enSubtitle = `${startStationRu?.name ?? ""} - ${endStationRu?.name ?? ""}`;
|
||||
const zhSubtitle = `${startStation?.name ?? ""} - ${endStation?.name ?? ""}`;
|
||||
const subtitle = language === "zh" ? zhSubtitle : enSubtitle;
|
||||
|
||||
return (
|
||||
<div className={styles["route-widget"]} style={{ position: "relative" }}>
|
||||
<div className={styles["route-widget-number"]}>
|
||||
{routeData?.route_sys_number || ""}
|
||||
</div>
|
||||
<div className={styles["route-widget-content"]}>
|
||||
<div
|
||||
className={[
|
||||
styles["route-widget-label"],
|
||||
shouldAnimate(startStation?.name, 18) ? styles["marquee"] : "",
|
||||
getLabelSizeClass(startStation?.name),
|
||||
].join(" ")}
|
||||
title={startStation?.name}
|
||||
>
|
||||
{startStation?.name}
|
||||
</div>
|
||||
<div
|
||||
className={[
|
||||
styles["route-widget-label"],
|
||||
shouldAnimate(endStation?.name, 18) ? styles["marquee"] : "",
|
||||
getLabelSizeClass(endStation?.name),
|
||||
].join(" ")}
|
||||
title={endStation?.name}
|
||||
>
|
||||
{endStation?.name}
|
||||
</div>
|
||||
<div
|
||||
className={[
|
||||
styles["route-widget-subtitle"],
|
||||
shouldAnimate(subtitle, 50) ? styles["marquee"] : "",
|
||||
].join(" ")}
|
||||
title={subtitle}
|
||||
>
|
||||
{subtitle}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user