feat: appeal widget and right widget update
This commit is contained in:
@@ -47,6 +47,16 @@ function darkenHex(hex: string, amount: number): string {
|
|||||||
return `#${dr.toString(16).padStart(2, "0")}${dg.toString(16).padStart(2, "0")}${db.toString(16).padStart(2, "0")}`;
|
return `#${dr.toString(16).padStart(2, "0")}${dg.toString(16).padStart(2, "0")}${db.toString(16).padStart(2, "0")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lightenRgbString(hex: string, amount: number): string | null {
|
||||||
|
const rgb = hexToRgbString(hex);
|
||||||
|
if (!rgb) return null;
|
||||||
|
const [r, g, b] = rgb.split(",").map(Number);
|
||||||
|
const lr = Math.round(r + (255 - r) * amount);
|
||||||
|
const lg = Math.round(g + (255 - g) * amount);
|
||||||
|
const lb = Math.round(b + (255 - b) * amount);
|
||||||
|
return `${lr}, ${lg}, ${lb}`;
|
||||||
|
}
|
||||||
|
|
||||||
function applyCarrierColors(carrier: { main_color?: string; left_color?: string; right_color?: string }) {
|
function applyCarrierColors(carrier: { main_color?: string; left_color?: string; right_color?: string }) {
|
||||||
const mainColor = carrier.main_color || "#006f3a";
|
const mainColor = carrier.main_color || "#006f3a";
|
||||||
const leftColor = carrier.left_color || "#006f3a";
|
const leftColor = carrier.left_color || "#006f3a";
|
||||||
@@ -60,6 +70,7 @@ function applyCarrierColors(carrier: { main_color?: string; left_color?: string;
|
|||||||
document.documentElement.style.setProperty("--carrier-left-rgb", hexToRgbString(leftColor) ?? "0, 111, 58");
|
document.documentElement.style.setProperty("--carrier-left-rgb", hexToRgbString(leftColor) ?? "0, 111, 58");
|
||||||
document.documentElement.style.setProperty("--carrier-right", rightColor);
|
document.documentElement.style.setProperty("--carrier-right", rightColor);
|
||||||
document.documentElement.style.setProperty("--carrier-right-rgb", hexToRgbString(rightColor) ?? "0, 111, 58");
|
document.documentElement.style.setProperty("--carrier-right-rgb", hexToRgbString(rightColor) ?? "0, 111, 58");
|
||||||
|
document.documentElement.style.setProperty("--carrier-right-menu-rgb", lightenRgbString(rightColor, 0.38) ?? "179, 165, 152");
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApiStore {
|
class ApiStore {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
|
|
||||||
const LANGUAGES = {
|
const LANGUAGES = {
|
||||||
EN: "en",
|
EN: "en",
|
||||||
@@ -18,6 +18,26 @@ const ListHeader = function ListHeader({
|
|||||||
isTransferWidgetOpen,
|
isTransferWidgetOpen,
|
||||||
onBackToNearest,
|
onBackToNearest,
|
||||||
}) {
|
}) {
|
||||||
|
const [isIdle, setIsIdle] = useState(false);
|
||||||
|
const timerRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const resetTimer = () => {
|
||||||
|
setIsIdle(false);
|
||||||
|
clearTimeout(timerRef.current);
|
||||||
|
timerRef.current = setTimeout(() => setIsIdle(true), 15000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const events = ["pointermove", "pointerdown", "touchstart", "keydown"];
|
||||||
|
events.forEach((e) => window.addEventListener(e, resetTimer));
|
||||||
|
resetTimer();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timerRef.current);
|
||||||
|
events.forEach((e) => window.removeEventListener(e, resetTimer));
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const getTitle = () => {
|
const getTitle = () => {
|
||||||
return selectedLanguageRight === LANGUAGES.RU
|
return selectedLanguageRight === LANGUAGES.RU
|
||||||
? "Достопримечательности"
|
? "Достопримечательности"
|
||||||
@@ -41,14 +61,11 @@ const ListHeader = function ListHeader({
|
|||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="21"
|
width="20"
|
||||||
height="12"
|
height="20"
|
||||||
viewBox="0 0 21 12"
|
viewBox="0 0 21 12"
|
||||||
fill="none"
|
fill="none"
|
||||||
style={{
|
className={`chevron-svg${isOpen ? " is-open" : ""}${isIdle ? " is-idle" : ""}`}
|
||||||
transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
|
|
||||||
transition: "transform 0.15s ease-in-out",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<g clipPath="url(#clip0_658_91932)">
|
<g clipPath="url(#clip0_658_91932)">
|
||||||
<path
|
<path
|
||||||
|
|||||||
@@ -682,7 +682,7 @@ const SightFrame = observer(({ media, sight_id, sight_name }) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="sight-frame-menu">
|
<div className="sight-frame-menu" style={selectedSection !== 0 ? { paddingLeft: '50px' } : undefined}>
|
||||||
{selectedSection !== 0 && (
|
{selectedSection !== 0 && (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import {
|
|||||||
UNPASSED_STATION_COLOR,
|
UNPASSED_STATION_COLOR,
|
||||||
BUS_COLOR,
|
BUS_COLOR,
|
||||||
BASE_ICON_SIZE,
|
BASE_ICON_SIZE,
|
||||||
CLUSTER_RADIUS_BASE,
|
|
||||||
} from "./Constants";
|
} from "./Constants";
|
||||||
import { SCALE_FACTOR } from "../../assets/Constants";
|
import { SCALE_FACTOR } from "../../assets/Constants";
|
||||||
import { apiStore } from "../../api/ApiStore/store";
|
import { apiStore } from "../../api/ApiStore/store";
|
||||||
@@ -2551,14 +2550,8 @@ export const WebGLMap = observer(() => {
|
|||||||
const rx = cluster.longitude;
|
const rx = cluster.longitude;
|
||||||
const ry = cluster.latitude;
|
const ry = cluster.latitude;
|
||||||
|
|
||||||
const iconSizePercent = resolveSightIconSizePercent();
|
|
||||||
const iconSize =
|
|
||||||
SIGHT_ICON_BASE_SIZE * clamp(iconSizePercent / 100, 0.1, 10);
|
|
||||||
|
|
||||||
const screenX = (rx * scale + position.x) / dpr;
|
const screenX = (rx * scale + position.x) / dpr;
|
||||||
const screenY = (ry * scale + position.y) / dpr;
|
const screenY = (ry * scale + position.y) / dpr;
|
||||||
const iconLeft = screenX - iconSize / 2;
|
|
||||||
const iconTop = screenY - iconSize / 2;
|
|
||||||
|
|
||||||
const isExpanded = activeClusterId === cluster.id;
|
const isExpanded = activeClusterId === cluster.id;
|
||||||
const selectedSightInCluster = cluster.sights.find(
|
const selectedSightInCluster = cluster.sights.find(
|
||||||
@@ -2570,6 +2563,20 @@ export const WebGLMap = observer(() => {
|
|||||||
const selectedIsCustomInCluster =
|
const selectedIsCustomInCluster =
|
||||||
selectedSightInCluster?.is_default_icon === false &&
|
selectedSightInCluster?.is_default_icon === false &&
|
||||||
selectedHasIconInCluster;
|
selectedHasIconInCluster;
|
||||||
|
|
||||||
|
const iconSizePercent = resolveSightIconSizePercent(
|
||||||
|
cluster.sights[0],
|
||||||
|
);
|
||||||
|
const clusterCustomScaleFactor = selectedIsCustomInCluster
|
||||||
|
? scale / Math.max(customSightIconBaseScaleRef.current ?? 1, 1e-6)
|
||||||
|
: 1;
|
||||||
|
const iconSize =
|
||||||
|
SIGHT_ICON_BASE_SIZE *
|
||||||
|
clamp(iconSizePercent / 100, 0.1, 10) *
|
||||||
|
clusterCustomScaleFactor;
|
||||||
|
|
||||||
|
const iconLeft = screenX - iconSize;
|
||||||
|
const iconTop = screenY - iconSize;
|
||||||
const hasSelectedAltIconInCluster =
|
const hasSelectedAltIconInCluster =
|
||||||
selectedSightInCluster != null &&
|
selectedSightInCluster != null &&
|
||||||
selectedIsCustomInCluster &&
|
selectedIsCustomInCluster &&
|
||||||
@@ -2643,13 +2650,10 @@ export const WebGLMap = observer(() => {
|
|||||||
onTouchEnd={handleClusterClick}
|
onTouchEnd={handleClusterClick}
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
left: iconLeft - CLUSTER_RADIUS_BASE - 10,
|
left: iconLeft - 25,
|
||||||
top: iconTop - CLUSTER_RADIUS_BASE - 10,
|
top: iconTop - 25,
|
||||||
width: iconSize + CLUSTER_RADIUS_BASE * 2 + 20,
|
width: iconSize + 50,
|
||||||
height: iconSize + CLUSTER_RADIUS_BASE * 2 + 20,
|
height: iconSize + 50,
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
userSelect: "none",
|
userSelect: "none",
|
||||||
@@ -2662,15 +2666,24 @@ export const WebGLMap = observer(() => {
|
|||||||
}),
|
}),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ position: "relative" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
left: 25,
|
||||||
|
top: 25,
|
||||||
|
width: iconSize,
|
||||||
|
height: iconSize,
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src={clusterIconUrl}
|
src={clusterIconUrl}
|
||||||
alt=""
|
alt=""
|
||||||
width={iconSize}
|
|
||||||
height={iconSize}
|
|
||||||
style={{
|
style={{
|
||||||
display: "block",
|
display: "block",
|
||||||
pointerEvents: "none",
|
pointerEvents: "none",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
filter: hasSelectedSight
|
filter: hasSelectedSight
|
||||||
? hasSelectedAltIconInCluster
|
? hasSelectedAltIconInCluster
|
||||||
? "none"
|
? "none"
|
||||||
@@ -2683,6 +2696,7 @@ export const WebGLMap = observer(() => {
|
|||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: -6,
|
top: -6,
|
||||||
right: -6,
|
right: -6,
|
||||||
|
zIndex: 1,
|
||||||
width: 15,
|
width: 15,
|
||||||
height: 15,
|
height: 15,
|
||||||
borderRadius: "10px",
|
borderRadius: "10px",
|
||||||
@@ -2708,8 +2722,8 @@ export const WebGLMap = observer(() => {
|
|||||||
onMouseMove={handleCircleInteraction}
|
onMouseMove={handleCircleInteraction}
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
left: screenX - iconSize / 2,
|
left: screenX - iconSize,
|
||||||
top: screenY - iconSize / 2,
|
top: screenY - iconSize,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "flex-start",
|
alignItems: "flex-start",
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import "../../styles/SideMenu.css";
|
|||||||
import AppealWidget from "../widgets/AppealWidget";
|
import AppealWidget from "../widgets/AppealWidget";
|
||||||
import { useEffect, useState, useCallback, useRef } from "react";
|
import { useEffect, useState, useCallback, useRef } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import gouvermentImage from "../../assets/images/test-image.png";
|
|
||||||
import sideMenuPhoto from "/side-menu-photo.png";
|
import sideMenuPhoto from "/side-menu-photo.png";
|
||||||
import RouteWidget from "../widgets/RouteWidget";
|
import RouteWidget from "../widgets/RouteWidget";
|
||||||
import ContentAPI from "../../api/content/content.api";
|
import ContentAPI from "../../api/content/content.api";
|
||||||
@@ -455,7 +454,7 @@ const SideMenu = observer(({ onMenuToggle }) => {
|
|||||||
: "Governor's appeal"}
|
: "Governor's appeal"}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="side-menu-buttons">
|
<div className="side-menu-buttons" style={{ marginTop: route?.governor_appeal > 0 ? '40px' : '260px' }}>
|
||||||
<div
|
<div
|
||||||
onPointerUp={() => {
|
onPointerUp={() => {
|
||||||
if (!isSightsOpen) {
|
if (!isSightsOpen) {
|
||||||
@@ -583,11 +582,17 @@ const SideMenu = observer(({ onMenuToggle }) => {
|
|||||||
<RouteWidget />
|
<RouteWidget />
|
||||||
|
|
||||||
<AppealWidget
|
<AppealWidget
|
||||||
widgetImgPath={gouvermentImage}
|
widgetImgPath={(() => {
|
||||||
|
const m = sightArticles.get(route?.governor_appeal + "_ru")?.media;
|
||||||
|
const mediaId = Array.isArray(m) ? m[0]?.id : m?.id;
|
||||||
|
return mediaId ? getMediaUrl(mediaId) : undefined;
|
||||||
|
})()}
|
||||||
|
isOpen={isWidgetOpen}
|
||||||
style={{
|
style={{
|
||||||
transform: isWidgetOpen ? "translateX(0)" : "translateX(-200%)",
|
transform: isWidgetOpen ? "translateX(0)" : "translateX(-200%)",
|
||||||
transition: "transform 0.5s ease",
|
transition: "transform 0.5s ease",
|
||||||
zIndex: -1,
|
zIndex: -1,
|
||||||
|
pointerEvents: isWidgetOpen ? "auto" : "none",
|
||||||
}}
|
}}
|
||||||
widgetLabel={
|
widgetLabel={
|
||||||
selectedLanguage == "ru"
|
selectedLanguage == "ru"
|
||||||
|
|||||||
@@ -1,11 +1,29 @@
|
|||||||
|
import { useRef, useEffect } from 'react'
|
||||||
import '../../styles/AppealWidget.css'
|
import '../../styles/AppealWidget.css'
|
||||||
|
import { TouchableLayout } from '../TouchableLayout'
|
||||||
|
|
||||||
|
function AppealWidget({widgetImgPath, widgetLabel, widgetText, style, isOpen}) {
|
||||||
|
const stopProp = (e) => { e.stopPropagation(); e.preventDefault(); };
|
||||||
|
const layoutRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen && layoutRef.current) {
|
||||||
|
const scrollable = layoutRef.current.querySelector('.scrollable');
|
||||||
|
if (scrollable) scrollable.scrollTop = 0;
|
||||||
|
}
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
function AppealWidget({widgetImgPath, widgetLabel, widgetText, style}) {
|
|
||||||
return (
|
return (
|
||||||
<div style={style} className='dynamic-widget'>
|
<div style={style} className='dynamic-widget'
|
||||||
<img className='dynamic-widget-image' src={widgetImgPath} />
|
onPointerDown={stopProp}
|
||||||
|
onPointerMove={stopProp}
|
||||||
|
onPointerUp={stopProp}
|
||||||
|
>
|
||||||
|
{widgetImgPath && <img className='dynamic-widget-image' src={widgetImgPath} />}
|
||||||
<div className='dynamic-widget-label'>{widgetLabel}</div>
|
<div className='dynamic-widget-label'>{widgetLabel}</div>
|
||||||
|
<TouchableLayout ref={layoutRef} className="dynamic-widget-text-scroll" maxHeight="calc(100vh - 150px - 100px - 300px)">
|
||||||
<div className='dynamic-widget-text'>{widgetText}</div>
|
<div className='dynamic-widget-text'>{widgetText}</div>
|
||||||
|
</TouchableLayout>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,37 +5,57 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 420px;
|
width: 420px;
|
||||||
|
max-height: calc(100vh - 150px - 100px);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: linear-gradient(
|
background:
|
||||||
|
linear-gradient(
|
||||||
114deg,
|
114deg,
|
||||||
rgba(255, 255, 255, 0) 8.71%,
|
rgba(255, 255, 255, 0) 8.71%,
|
||||||
rgba(255, 255, 255, 0.16) 69.69%
|
rgba(255, 255, 255, 0.16) 69.69%
|
||||||
),
|
),
|
||||||
var(--carrier-main, #006F3A);
|
var(--carrier-left, #006F3A);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
touch-action: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dynamic-widget-image {
|
.dynamic-widget-image {
|
||||||
border-radius-top-left: 10px;
|
|
||||||
border-radius-top-right: 10px;
|
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
width: 412px;
|
width: 412px;
|
||||||
|
border-radius: 6px 6px 0 0;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dynamic-widget-label {
|
.dynamic-widget-label {
|
||||||
width: 380px;
|
width: 380px;
|
||||||
margin-top: 29px;
|
margin-top: 20px;
|
||||||
|
margin-bottom: 5px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dynamic-widget-text {
|
.dynamic-widget-text-scroll {
|
||||||
margin-top: 16px;
|
margin-top: 0;
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
width: 380px;
|
flex: 1;
|
||||||
font-size: 16px;
|
min-height: 0;
|
||||||
font-weight: 300;
|
}
|
||||||
line-height: 150%;
|
|
||||||
|
.dynamic-widget-text-scroll.scrollable-container {
|
||||||
|
margin: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-widget-text-scroll .scrollable-viewport {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-widget-text {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 190%;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
@keyframes pulse-chevron {
|
||||||
|
0% { transform: rotate(var(--r, 0deg)) translateY(0px) scale(1); }
|
||||||
|
40% { transform: rotate(var(--r, 0deg)) translateY(-4px) scale(1.12); }
|
||||||
|
60% { transform: rotate(var(--r, 0deg)) translateY(-5px) scale(1.14); }
|
||||||
|
100% { transform: rotate(var(--r, 0deg)) translateY(0px) scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.chevron-svg {
|
||||||
|
font-size: 20px;
|
||||||
|
animation: pulse-chevron 1.2s ease-in-out infinite;
|
||||||
|
animation-play-state: paused;
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chevron-svg.is-idle {
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chevron-svg.is-open {
|
||||||
|
--r: 180deg;
|
||||||
|
}
|
||||||
|
|
||||||
.right-widget {
|
.right-widget {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 32px;
|
right: 32px;
|
||||||
@@ -17,7 +39,7 @@
|
|||||||
rgba(255, 255, 255, 0) 8.71%,
|
rgba(255, 255, 255, 0) 8.71%,
|
||||||
rgba(255, 255, 255, 0.16) 69.69%
|
rgba(255, 255, 255, 0.16) 69.69%
|
||||||
),
|
),
|
||||||
var(--carrier-right, #006f3a);
|
var(--carrier-right, #806C59);
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
max-height: 68px;
|
max-height: 68px;
|
||||||
@@ -65,7 +87,7 @@
|
|||||||
|
|
||||||
background-color: color-mix(
|
background-color: color-mix(
|
||||||
in srgb,
|
in srgb,
|
||||||
var(--carrier-right, #006f3a) 80%,
|
var(--carrier-right, #806C59) 80%,
|
||||||
black
|
black
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -198,7 +220,7 @@
|
|||||||
rgba(255, 255, 255, 0) 8.71%,
|
rgba(255, 255, 255, 0) 8.71%,
|
||||||
rgba(255, 255, 255, 0.16) 69.69%
|
rgba(255, 255, 255, 0.16) 69.69%
|
||||||
),
|
),
|
||||||
var(--carrier-right, #006f3a);
|
var(--carrier-right, #806C59);
|
||||||
max-height: calc(100vh - 128px);
|
max-height: calc(100vh - 128px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +263,7 @@
|
|||||||
rgba(255, 255, 255, 0.22) 0%,
|
rgba(255, 255, 255, 0.22) 0%,
|
||||||
rgba(255, 255, 255, 0.04) 100%
|
rgba(255, 255, 255, 0.04) 100%
|
||||||
),
|
),
|
||||||
rgba(var(--carrier-right-rgb, 0, 111, 58), 0.72);
|
rgba(var(--carrier-right-rgb, 128, 108, 89), 0.72);
|
||||||
box-shadow: 4px 4px 12px 0px rgba(255, 255, 255, 0.12) inset;
|
box-shadow: 4px 4px 12px 0px rgba(255, 255, 255, 0.12) inset;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: white;
|
color: white;
|
||||||
@@ -250,6 +272,16 @@
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sight-frame-title:not(.intro-title) {
|
||||||
|
background:
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(255, 255, 255, 0.2) 0%,
|
||||||
|
rgba(255, 255, 255, 0) 100%
|
||||||
|
),
|
||||||
|
rgba(var(--carrier-right-menu-rgb, 179, 165, 152), 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
.sight-frame-title p {
|
.sight-frame-title p {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
@@ -308,7 +340,7 @@
|
|||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
to right,
|
to right,
|
||||||
transparent 35%,
|
transparent 35%,
|
||||||
color-mix(in srgb, var(--carrier-right, #006f3a) 80%, black) 50%,
|
color-mix(in srgb, var(--carrier-right, #806C59) 80%, black) 50%,
|
||||||
transparent 65%
|
transparent 65%
|
||||||
);
|
);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
@@ -336,7 +368,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-around;
|
justify-content: space-evenly;
|
||||||
border-radius: 0px 0px 10px 10px;
|
border-radius: 0px 0px 10px 10px;
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.8);
|
border-top: 1px solid rgba(255, 255, 255, 0.8);
|
||||||
background:
|
background:
|
||||||
@@ -345,7 +377,7 @@
|
|||||||
rgba(255, 255, 255, 0.2) 0%,
|
rgba(255, 255, 255, 0.2) 0%,
|
||||||
rgba(255, 255, 255, 0) 100%
|
rgba(255, 255, 255, 0) 100%
|
||||||
),
|
),
|
||||||
rgba(var(--carrier-right-rgb, 0, 111, 58), 0.4);
|
rgba(var(--carrier-right-menu-rgb, 179, 165, 152), 0.4);
|
||||||
box-shadow: 4px 4px 12px 0px rgba(255, 255, 255, 0.12) inset;
|
box-shadow: 4px 4px 12px 0px rgba(255, 255, 255, 0.12) inset;
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -360,7 +392,6 @@
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
transition:
|
transition:
|
||||||
background-color 0.1s ease,
|
background-color 0.1s ease,
|
||||||
@@ -368,8 +399,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sight-frame-menu-point.active {
|
.sight-frame-menu-point.active {
|
||||||
border-bottom: 2px solid #fff;
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
border-bottom: 2px solid #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sight-frame-text-wrapper::-webkit-scrollbar-track {
|
.sight-frame-text-wrapper::-webkit-scrollbar-track {
|
||||||
@@ -751,7 +782,7 @@
|
|||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
background: var(--carrier-right, #006f3a);
|
background: var(--carrier-right, #806C59);
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
.side-menu-buttons {
|
.side-menu-buttons {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
margin-top: 260px;
|
margin-top: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.side-menu-button {
|
.side-menu-button {
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ export const CarrierCreatePage = observer(() => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<p className="text-xs text-gray-500 pl-1">
|
<p className="text-xs text-gray-500 pl-1">
|
||||||
Используется в: виджет маршрута, виджет обращений, значки на карте, скопление достопримечательностей на карте, информационный виджет
|
Используется в: виджет обращений, значки на карте, скопление достопримечательностей на карте, информационный виджет
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ import {
|
|||||||
UploadMediaDialog,
|
UploadMediaDialog,
|
||||||
} from "@shared";
|
} from "@shared";
|
||||||
|
|
||||||
type ColorFields = { main_color: string; left_color: string; right_color: string };
|
type ColorFields = {
|
||||||
|
main_color: string;
|
||||||
|
left_color: string;
|
||||||
|
right_color: string;
|
||||||
|
};
|
||||||
|
|
||||||
const colorFields = (data: ColorFields) => ({
|
const colorFields = (data: ColorFields) => ({
|
||||||
main_color: data.main_color,
|
main_color: data.main_color,
|
||||||
@@ -130,7 +134,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
carrierData.ru?.slogan || "",
|
carrierData.ru?.slogan || "",
|
||||||
carrierData.ru?.logo || "",
|
carrierData.ru?.logo || "",
|
||||||
"ru",
|
"ru",
|
||||||
colors
|
colors,
|
||||||
);
|
);
|
||||||
setEditCarrierData(
|
setEditCarrierData(
|
||||||
carrierData.en?.full_name || "",
|
carrierData.en?.full_name || "",
|
||||||
@@ -138,7 +142,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
carrierData.en?.city_id || 0,
|
carrierData.en?.city_id || 0,
|
||||||
carrierData.en?.slogan || "",
|
carrierData.en?.slogan || "",
|
||||||
carrierData.en?.logo || "",
|
carrierData.en?.logo || "",
|
||||||
"en"
|
"en",
|
||||||
);
|
);
|
||||||
setEditCarrierData(
|
setEditCarrierData(
|
||||||
carrierData.zh?.full_name || "",
|
carrierData.zh?.full_name || "",
|
||||||
@@ -146,7 +150,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
carrierData.zh?.city_id || 0,
|
carrierData.zh?.city_id || 0,
|
||||||
carrierData.zh?.slogan || "",
|
carrierData.zh?.slogan || "",
|
||||||
carrierData.zh?.logo || "",
|
carrierData.zh?.logo || "",
|
||||||
"zh"
|
"zh",
|
||||||
);
|
);
|
||||||
setInitialCityName(carrierData.ru?.city || "");
|
setInitialCityName(carrierData.ru?.city || "");
|
||||||
}
|
}
|
||||||
@@ -185,7 +189,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
editCarrierData.city_id,
|
editCarrierData.city_id,
|
||||||
editCarrierData[language].slogan,
|
editCarrierData[language].slogan,
|
||||||
media.id,
|
media.id,
|
||||||
language
|
language,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -267,7 +271,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
Number(e.target.value),
|
Number(e.target.value),
|
||||||
editCarrierData[language].slogan,
|
editCarrierData[language].slogan,
|
||||||
editCarrierData.logo,
|
editCarrierData.logo,
|
||||||
language
|
language,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -291,7 +295,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
editCarrierData.city_id,
|
editCarrierData.city_id,
|
||||||
editCarrierData[language].slogan,
|
editCarrierData[language].slogan,
|
||||||
editCarrierData.logo,
|
editCarrierData.logo,
|
||||||
language
|
language,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -308,7 +312,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
editCarrierData.city_id,
|
editCarrierData.city_id,
|
||||||
editCarrierData[language].slogan,
|
editCarrierData[language].slogan,
|
||||||
editCarrierData.logo,
|
editCarrierData.logo,
|
||||||
language
|
language,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -324,7 +328,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
editCarrierData.city_id,
|
editCarrierData.city_id,
|
||||||
e.target.value,
|
e.target.value,
|
||||||
editCarrierData.logo,
|
editCarrierData.logo,
|
||||||
language
|
language,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -342,12 +346,13 @@ export const CarrierEditPage = observer(() => {
|
|||||||
editCarrierData[language].slogan,
|
editCarrierData[language].slogan,
|
||||||
editCarrierData.logo,
|
editCarrierData.logo,
|
||||||
language,
|
language,
|
||||||
{ ...colorFields(editCarrierData), main_color: val }
|
{ ...colorFields(editCarrierData), main_color: val },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<p className="text-xs text-gray-500 pl-1">
|
<p className="text-xs text-gray-500 pl-1">
|
||||||
Используется в: виджет маршрута, виджет обращений, значки на карте, скопление достопримечательностей на карте, информационный виджет
|
Используется в: значки на карте, скопление достопримечательностей
|
||||||
|
на карте, информационный виджет
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
@@ -362,12 +367,13 @@ export const CarrierEditPage = observer(() => {
|
|||||||
editCarrierData[language].slogan,
|
editCarrierData[language].slogan,
|
||||||
editCarrierData.logo,
|
editCarrierData.logo,
|
||||||
language,
|
language,
|
||||||
{ ...colorFields(editCarrierData), left_color: val }
|
{ ...colorFields(editCarrierData), left_color: val },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<p className="text-xs text-gray-500 pl-1">
|
<p className="text-xs text-gray-500 pl-1">
|
||||||
Используется в: боковое меню, левый виджет достопримечательности
|
Используется в: виджет обращений, боковое меню (фон, список
|
||||||
|
остановок), левый виджет достопримечательности
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
@@ -382,12 +388,13 @@ export const CarrierEditPage = observer(() => {
|
|||||||
editCarrierData[language].slogan,
|
editCarrierData[language].slogan,
|
||||||
editCarrierData.logo,
|
editCarrierData.logo,
|
||||||
language,
|
language,
|
||||||
{ ...colorFields(editCarrierData), right_color: val }
|
{ ...colorFields(editCarrierData), right_color: val },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<p className="text-xs text-gray-500 pl-1">
|
<p className="text-xs text-gray-500 pl-1">
|
||||||
Используется в: список достопримечательностей, страница достопримечательности
|
Используется в: список достопримечательностей (фон, карточки),
|
||||||
|
правый виджет достопримечательности
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -465,7 +472,7 @@ export const CarrierEditPage = observer(() => {
|
|||||||
editCarrierData.city_id,
|
editCarrierData.city_id,
|
||||||
editCarrierData[language].slogan,
|
editCarrierData[language].slogan,
|
||||||
"",
|
"",
|
||||||
language
|
language,
|
||||||
);
|
);
|
||||||
setIsDeleteLogoModalOpen(false);
|
setIsDeleteLogoModalOpen(false);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -125,7 +125,12 @@ export const LeftSidebar = observer(({ open, onToggle }: LeftSidebarProps) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Кнопки — .side-menu-buttons */}
|
{/* Кнопки — .side-menu-buttons */}
|
||||||
<div style={{ width: 220, marginTop: 260 }}>
|
<div
|
||||||
|
style={{
|
||||||
|
width: 220,
|
||||||
|
marginTop: routeData?.governor_appeal || 0 > 0 ? 40 : 260,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: "#fff",
|
backgroundColor: "#fff",
|
||||||
|
|||||||
Reference in New Issue
Block a user