This commit is contained in:
2025-06-17 15:31:01 +05:00
parent facb76e904
commit 8b8883bb0d
13 changed files with 126 additions and 71 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
function Badge({ count }: { count: number }) {
return (
<div className="size-[1.389vw] rounded-full bg-[#F8F7FE] caption-xs text-[#7B60F3] flex justify-center items-center font-medium font-mono">
<div className="size-[1.389vw] rounded-full bg-[#F8F7FE] caption-xs text-[#7B60F3] flex justify-center items-center font-medium afont-mono">
{count}
</div>
);
+6 -3
View File
@@ -34,8 +34,8 @@ export default function DesktopCard({ server }: IDesktopCardProps) {
>
<Button
variant="secondary"
size="medium"
className="absolute top-[0.347vw] right-[0.347vw] cursor-pointer flex items-center justify-center"
size="small"
className="absolute top-[0.556vw] right-[0.556vw] cursor-pointer flex items-center justify-center"
onClick={() => setModal(<EditTable table={server} />)}
>
<span className="text-[#7D7D7D] w-[0.972vw] h-[0.972vw]">
@@ -84,7 +84,10 @@ export default function DesktopCard({ server }: IDesktopCardProps) {
</Button>
</div>
) : server.status === "offline" ? (
<Button variant="critical" className="hover:bg-[#FEF3F2]">
<Button
variant="critical"
className="hover:bg-[#FEF3F2] !cursor-default"
>
<span className="text-[#FF4517] size-[0.972vw]">
<UnlinkIcon />
</span>
+3 -4
View File
@@ -14,8 +14,7 @@ function SearchInput(
return (
<div
className={clsx(
"p-[0.556vw] bg-[#F6F6F6] rounded-[0.833vw] w-full flex items-center gap-[1.111vw] hover:bg-[#F0F0F0]",
!props.onEnter && "px-[1.111vw] py-[1.215vw]"
"p-[0.556vw] bg-[#F6F6F6] rounded-[0.833vw] w-full flex items-center gap-[1.111vw] hover:bg-[#F0F0F0] px-[1.111vw] py-[1.215vw]"
)}
>
<div className="flex gap-[0.566vw] items-center flex-1">
@@ -51,11 +50,11 @@ function SearchInput(
<CloseIcon />
</div>
</button>
{props.onEnter && (
{/* {pr ops.onEnter && (
<Button size="small" disabled={!props.value} onClick={props.onEnter}>
Искать
</Button>
)}
)} */}
</div>
</div>
);
+1 -1
View File
@@ -1,5 +1,5 @@
import { motion } from "motion/react";
import { Comment } from "../types/Comments";
import { Comment } from "../types/Comment";
import { format } from "date-fns";
function SessionCommentItem({ comment }: { comment: Comment }) {
+30 -9
View File
@@ -1,11 +1,14 @@
import { useRef } from "react";
import { useRef, useState } from "react";
import SendIcon from "./icons/SendIcon";
import Button from "./Button";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import api from "../utils/api";
import { Comment } from "../types/Comments";
import { Comment } from "../types/Comment";
import SessionCommentItem from "./SessionCommentItem";
import { AnimatePresence } from "motion/react";
import { AnimatePresence, motion } from "motion/react";
import { groupByCreatedAt } from "../utils/groupByCreatedAt";
import { format, isToday } from "date-fns";
import { ru } from "date-fns/locale";
function SessionComments({ sessionId }: { sessionId: string }) {
const textareaRef = useRef<HTMLTextAreaElement>(null);
@@ -49,9 +52,10 @@ function SessionComments({ sessionId }: { sessionId: string }) {
const queryClient = useQueryClient();
const { data: comments } = useQuery({
const { data: grouppedComments } = useQuery({
queryKey: ["sessions", "comments", sessionId],
queryFn: () => api.get(`comments/${sessionId}`).json<Comment[]>(),
select: groupByCreatedAt,
});
const { mutate: createComment } = useMutation({
@@ -76,6 +80,7 @@ function SessionComments({ sessionId }: { sessionId: string }) {
createComment(textarea.value);
textarea.value = "";
setValue("");
handleTextareaInput();
};
@@ -86,13 +91,26 @@ function SessionComments({ sessionId }: { sessionId: string }) {
}
};
const [value, setValue] = useState("");
return (
<div className="outline flex flex-col flex-1 outline-[#D6D6D6]">
<div className="relative h-full flex flex-col-reverse gap-[0.833vw] overflow-y-auto p-[1.111vw] [scrollbar-width:thin]">
<AnimatePresence mode="wait">
{comments && comments.length > 0 ? (
comments.map((comment) => (
<SessionCommentItem key={comment.id} comment={comment} />
{grouppedComments && grouppedComments.length > 0 ? (
grouppedComments.map(([timestamp, comments], index) => (
<motion.div layout className="space-y-[1.111vw]" key={index}>
<p className="text-center text-[#BDBDBD] caption-s">
{isToday(new Date(timestamp))
? "Сегодня"
: format(new Date(timestamp), "d MMMM", { locale: ru })}
</p>
<div className="flex flex-col-reverse gap-[0.833vw]">
{comments.map((comment) => (
<SessionCommentItem key={comment.id} comment={comment} />
))}
</div>
</motion.div>
))
) : (
<div className="flex flex-col gap-[1.111vw] items-center justify-center h-full">
@@ -124,6 +142,9 @@ function SessionComments({ sessionId }: { sessionId: string }) {
name="comment"
className="w-[17.083vw] outline-none text-s resize-none self-center"
placeholder="Расскажите, как все прошло"
onChange={(e) => {
setValue(e.target.value);
}}
style={{
wordWrap: "break-word",
overflowY: "hidden",
@@ -131,8 +152,8 @@ function SessionComments({ sessionId }: { sessionId: string }) {
onInput={handleTextareaInput}
onKeyDown={handleKeyDown}
/>
<Button variant="cta" size="large" type="submit">
<span className="w-[1.111vw] h-[1.111vw] text-white">
<Button variant="cta" size="large" type="submit" disabled={!value}>
<span className="size-[1.111vw] text-white">
<SendIcon />
</span>
</Button>
+3 -2
View File
@@ -1,8 +1,9 @@
function StartSessionIcon() {
return (
<svg viewBox="0 0 7 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width={20} height={20} rx={10} fill="#fff" fillOpacity={0.1} />
<path
d="M5.938 3.595a.5.5 0 0 1 0 .81L1.293 7.758A.5.5 0 0 1 .5 7.353V.647a.5.5 0 0 1 .793-.405z"
d="M13.438 9.595a.5.5 0 0 1 0 .81l-4.645 3.353A.5.5 0 0 1 8 13.353V6.647a.5.5 0 0 1 .793-.405z"
fill="currentColor"
/>
</svg>
+18 -18
View File
@@ -226,26 +226,26 @@ export default function CreateSessionModal({ targetServerId }: Props) {
</div>
</div>
)}
<Button
type="submit"
disabled={
!ref.current?.checkValidity() ||
!selectedServer ||
!selectedApp ||
servers?.find((server) => server.id === selectedServer?.id)
?.sessions?.[0]?.status === "ending"
}
variant="cta"
size="large"
className="sticky bottom-0"
>
<div className="rounded-full bg-[#9184F6] in-disabled:bg-transparent px-[0.278vw] py-[0.208vw] size-[1.111vw]">
<div className="w-[0.694vw] h-[0.556vw]">
<div className="flex-1 flex flex-col justify-end">
<Button
type="submit"
disabled={
!ref.current?.checkValidity() ||
!selectedServer ||
!selectedApp ||
servers?.find((server) => server.id === selectedServer?.id)
?.sessions?.[0]?.status === "ending"
}
variant="cta"
size="large"
className="sticky bottom-0"
>
<div className="size-[1.111vw]">
<StartSessionIcon />
</div>
</div>
<p>Запустить сеанс</p>
</Button>
<span>Запустить сеанс</span>
</Button>
</div>
</div>
</form>
);
+1 -1
View File
@@ -18,7 +18,7 @@ function EditTable({ table }: { table: Server }) {
return api.put(`servers/${table.id}`, {
json: {
name: tableName,
location: tableDescription,
description: tableDescription,
},
});
},