feat: refactor ManagerSelect and ProjectSelector for improved positioning logic and integrate new utility function
This commit is contained in:
@@ -5,6 +5,7 @@ import clsx from "clsx";
|
||||
import CheckIcon from "./icons/CheckIcon";
|
||||
import { useClickAway } from "@uidotdev/usehooks";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import { getPositionAbove } from "../utils/getPositionAbove";
|
||||
|
||||
function ManagerSelect({
|
||||
placeholder,
|
||||
@@ -21,19 +22,15 @@ function ManagerSelect({
|
||||
const selectRef = useClickAway<HTMLDivElement>(() => setIsOpen(false));
|
||||
|
||||
useEffect(() => {
|
||||
const rect = selectRef.current?.getBoundingClientRect();
|
||||
if (rect) {
|
||||
setPosition(rect.top > window.innerHeight / 2 ? "top" : "bottom");
|
||||
}
|
||||
if (!isOpen || !selectRef.current) return;
|
||||
|
||||
setPosition(getPositionAbove(selectRef) ? "top" : "bottom");
|
||||
}, [isOpen, selectRef]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
if (isOpen) {
|
||||
const rect = selectRef.current?.getBoundingClientRect();
|
||||
if (rect) {
|
||||
setPosition(rect.top > window.innerHeight / 2 ? "top" : "bottom");
|
||||
}
|
||||
setPosition(getPositionAbove(selectRef) ? "top" : "bottom");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { App } from "../types/App";
|
||||
import ChevronDownIcon from "./icons/ChevronDownIcon";
|
||||
import CheckIcon from "./icons/CheckIcon";
|
||||
import { useClickAway } from "@uidotdev/usehooks";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import clsx from "clsx";
|
||||
import FlashIcon from "./icons/FlashIcon";
|
||||
import SortIcon from "./icons/SortIcon";
|
||||
import { getPositionAbove } from "../utils/getPositionAbove";
|
||||
|
||||
interface Props {
|
||||
projects: App[];
|
||||
@@ -24,19 +26,13 @@ function ProjectSelector({
|
||||
const selectRef = useClickAway<HTMLDivElement>(() => setIsOpen(false));
|
||||
|
||||
useEffect(() => {
|
||||
const rect = selectRef.current?.getBoundingClientRect();
|
||||
if (rect) {
|
||||
setPosition(rect.top > window.innerHeight / 2 ? "top" : "bottom");
|
||||
}
|
||||
setPosition(getPositionAbove(selectRef) ? "top" : "bottom");
|
||||
}, [isOpen, selectRef]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
if (isOpen) {
|
||||
const rect = selectRef.current?.getBoundingClientRect();
|
||||
if (rect) {
|
||||
setPosition(rect.top > window.innerHeight / 2 ? "top" : "bottom");
|
||||
}
|
||||
setPosition(getPositionAbove(selectRef) ? "top" : "bottom");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -61,13 +57,20 @@ function ProjectSelector({
|
||||
<div className="flex flex-col gap-[0.278vw]">
|
||||
<div className="caption-s font-medium text-[#7D7D7D]">Проект</div>
|
||||
<div className="flex items-center gap-[0.556vw]">
|
||||
<img src="/images/app_image.png" className="size-[1.111vw]" alt="" />
|
||||
<div className="text-s">{selectedProject?.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
<span className="size-[1.389vw] text-[#7D7D7D]">
|
||||
<ChevronDownIcon />
|
||||
</span>
|
||||
<div className="flex items-center gap-[0.556vw]">
|
||||
<img
|
||||
src="/images/app_image.png"
|
||||
className="size-[2.222vw]"
|
||||
alt="app_image"
|
||||
/>
|
||||
<span className="size-[1.389vw] text-[#7D7D7D]">
|
||||
<SortIcon />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
@@ -100,13 +103,15 @@ function ProjectSelector({
|
||||
</div>
|
||||
<img
|
||||
src="/images/app_image.png"
|
||||
className="size-[1.111vw]"
|
||||
className="size-[1.389vw]"
|
||||
alt=""
|
||||
/>
|
||||
<div className="flex items-center gap-[0.278vw]">
|
||||
<div className="text-s">{project.name}</div>
|
||||
{activeProject && project.name === activeProject.name && (
|
||||
<span className="size-[0.972vw] text-[#7B60F3]">⚡</span>
|
||||
<span className="size-[0.972vw] text-[#7B60F3]">
|
||||
<FlashIcon />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function CreateSessionModal({ targetServerId, client }: Props) {
|
||||
|
||||
const { data: managers } = useQuery({
|
||||
queryKey: ["managers"],
|
||||
queryFn: () => api.get("managers").json<Manager[]>(),
|
||||
queryFn: () => api.get("users").json<Manager[]>(),
|
||||
});
|
||||
|
||||
const targetServer = targetServerId
|
||||
@@ -176,6 +176,10 @@ export default function CreateSessionModal({ targetServerId, client }: Props) {
|
||||
selectedServer,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(managers);
|
||||
}, [managers]);
|
||||
|
||||
const ref = useRef<HTMLFormElement>(null);
|
||||
|
||||
return (
|
||||
@@ -246,20 +250,26 @@ export default function CreateSessionModal({ targetServerId, client }: Props) {
|
||||
</div>
|
||||
<div className="flex flex-col gap-y-[0.833vw]">
|
||||
<p className="title-s font-medium">Выберите параметры сеанса</p>
|
||||
<ManagerSelect placeholder="Менеджер сеанса" data={managers || []} />
|
||||
|
||||
{selectedServer &&
|
||||
selectedServer?.appsToServers &&
|
||||
selectedServer.appsToServers?.length > 0 && (
|
||||
<ProjectSelector
|
||||
activeProject={
|
||||
selectedServer?.sessions?.[0]?.status === "started"
|
||||
? selectedApp
|
||||
: null
|
||||
}
|
||||
projects={selectedServer?.appsToServers.map(({ app }) => app)}
|
||||
selectedProject={selectedApp}
|
||||
setSelectedProject={setSelectedApp}
|
||||
/>
|
||||
<>
|
||||
<ManagerSelect
|
||||
placeholder="Менеджер сеанса"
|
||||
data={managers || []}
|
||||
/>
|
||||
<ProjectSelector
|
||||
activeProject={
|
||||
selectedServer?.sessions?.[0]?.status === "started"
|
||||
? selectedApp
|
||||
: null
|
||||
}
|
||||
projects={selectedServer?.appsToServers.map(({ app }) => app)}
|
||||
selectedProject={selectedApp}
|
||||
setSelectedProject={setSelectedApp}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export function getPositionAbove(selectRef: React.RefObject<HTMLDivElement>) {
|
||||
const rect = selectRef.current.getBoundingClientRect();
|
||||
const dropdownHeight = 200;
|
||||
const margin = 8;
|
||||
|
||||
const spaceBelow = window.innerHeight - rect.bottom - margin;
|
||||
|
||||
const spaceAbove = rect.top - margin;
|
||||
|
||||
return spaceBelow < dropdownHeight && spaceAbove >= dropdownHeight;
|
||||
}
|
||||
Reference in New Issue
Block a user