This commit is contained in:
2026-03-22 21:14:40 +03:00
parent 8aa1182641
commit 2dbe7866ff
9 changed files with 174 additions and 60 deletions
+49 -24
View File
@@ -10,24 +10,20 @@ import {
import Logo from "../assets/logo.svg";
import LogoAlternative from "../assets/fully_alternative_logo.svg";
import {
Switch,
// AnimatedCanvas,
LoadingSpinner,
DatePicker,
TextPreloader,
// CoolMouseBg,
} from "../trash/trash-components";
import {
AdminReq,
AdminUserFRequest,
classUserFRequest,
RaspGet,
} from "../trash/req_mgr";
import { AdminReq, classUserFRequest, RaspGet } from "../trash/req_mgr";
import { AnimatePresence, LayoutGroup, motion } from "motion/react";
import { apiFormatDate, isTimeBeforeNow } from "../trash/dengi";
import { useAtom } from "jotai";
import { API_BASE_URL } from "../App";
import { copyDXLink, ifstyle } from "../trash/helpers";
import { useWebHaptics } from "web-haptics/react";
export function DX4App({
classIDAtom,
@@ -78,7 +74,7 @@ export function DX4App({
(err) => {
if (cancelled) return;
setRasp([true, "ошибка: " + err]);
}
},
);
} else {
if (cancelled) return;
@@ -133,15 +129,15 @@ export function DX4App({
if (classId !== "")
promises.push(
dengi_cash.withCacheAsync(`userfr-${classId}`, async () =>
classUserFRequest(API_BASE_URL, classId)
)
classUserFRequest(API_BASE_URL, classId),
),
);
else promises.push(Promise.resolve([0]));
if (adminId !== "")
promises.push(
dengi_cash.withCacheAsync(`admindata-${adminId}`, async () =>
AdminReq(API_BASE_URL, adminId)
)
AdminReq(API_BASE_URL, adminId),
),
);
else promises.push(Promise.resolve([0]));
Promise.all(promises).then(([classRes, adminRes]) => {
@@ -192,6 +188,9 @@ export function DX4App({
if (classId === "") {
setsetRoute(setRoute, "/");
}
const { trigger } = useWebHaptics();
const raspDragStartX = useRef(0);
return (
<>
<motion.div className="w-full h-screen flex flex-col items-center justify-center gap-5 overflow-x-hidden z-2">
@@ -236,7 +235,12 @@ export function DX4App({
>
<BiDotsHorizontalRounded
size={35}
onClick={() => setOpenUserSettings(!openUserSettings)}
onClick={() => {
setOpenUserSettings(!openUserSettings);
trigger([{ duration: 10 }, { delay: 100, duration: 10 }], {
intensity: 1,
});
}}
onContextMenu={(e) => {
e.preventDefault();
setPickmeMode(!pickmeMode);
@@ -269,7 +273,7 @@ export function DX4App({
{adminId != "" && managing && (
<motion.div
className="flex w-full justify-end"
className="flex w-full justify-end not-md:px-4"
layout="position"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
@@ -326,7 +330,28 @@ export function DX4App({
</a>
)}
</div>
<div className="relative">
<motion.div
className="relative min-h-[50vh]"
drag="x"
dragConstraints={{ top: 0, right: 0, bottom: 0, left: 0 }}
dragElastic={0.2}
onDragStart={(ev) => {
raspDragStartX.current = ev.clientX;
}}
onDragEnd={(ev) => {
if (raspDragStartX.current > ev.clientX + 150) {
const d = new Date(selectedDate);
d.setDate(d.getDate() + 1);
setSelectedDate(d);
trigger([{ duration: 10 }], { intensity: 1 });
} else if (raspDragStartX.current < ev.clientX - 150) {
const d = new Date(selectedDate);
d.setDate(d.getDate() - 1);
setSelectedDate(d);
trigger([{ duration: 10 }], { intensity: 1 });
}
}}
>
<LayoutGroup>
<RaspView {...{ rasp, pickmeMode, selectedDate }} />
</LayoutGroup>
@@ -343,7 +368,7 @@ export function DX4App({
<LoadingSpinner size={25} />
</motion.div>
)}
</div>
</motion.div>
</motion.div>
</motion.div>
</motion.div>
@@ -370,8 +395,8 @@ export const RaspView = memo(({ rasp, pickmeMode, selectedDate }) => {
key={selectedDate}
className={
"w-full border-collapse border-spacing-x-0 border-spacing-y-[10px] bg-gradient-to-br mb-10 " +
(pickmeMode ? "from-pink-400/30" : "from-zinc-800/40") +
" to-transparent rounded-2xl selectable"
(pickmeMode ? "from-pink-400/30" : "from-[#101011ee]") +
" to-[#030303fa] rounded-2xl"
}
onContextMenu={(ev) => {
ev.preventDefault();
@@ -419,7 +444,7 @@ export const RaspView = memo(({ rasp, pickmeMode, selectedDate }) => {
</th>
</tr>
</thead>
<tbody className="*:*:text-center *:*:py-2 *:not-last:border-b *:not-last:border-zinc-800 text-white">
<tbody className="*:*:text-center *:*:py-2 *:not-last:border-b *:not-last:border-zinc-800 text-white ">
{rasp[1].map((d, i) => (
<TableItem {...{ d }} key={`table-header-${i}`} />
))}
@@ -542,13 +567,13 @@ const UserSettings = memo(
>
{item[0]} {item[1]}
</div>
)
),
)}
</motion.div>
)}
</>
);
}
},
);
class GlobalListener {
@@ -592,10 +617,10 @@ const TableItem = memo(({ d }) => {
<tr
//layout="position"
className={
"transition-colors *:transition-colors " +
"transition-colors *:transition-colors last:*:first:rounded-bl-2xl last:*:last:rounded-br-2xl " +
(sel
? "bg-zinc-300/15 lg:hover:bg-zinc-300/20"
: " lg:hover:bg-zinc-300/15")
? "*:bg-zinc-300/15 lg:hover:*:bg-zinc-300/20"
: " lg:hover:*:bg-zinc-300/15")
}
onClick={() => {
setSel(!sel);
+12 -6
View File
@@ -22,6 +22,7 @@ import {
import { TableEditor } from "../trash/editorTable";
import { ifstyle } from "../trash/helpers";
import { API_BASE_URL } from "../App";
import { useWebHaptics } from "web-haptics/react";
export default function EditorPage(props) {
const [classId, _setUserId] = useAtom(props.classIDAtom);
@@ -49,17 +50,18 @@ export default function EditorPage(props) {
let cancelled = false;
const promises = [];
if (classId !== "")
// TODO: rewrite this bullshit into one pretty request
promises.push(
props.dengi_cash.withCacheAsync(`userfr-${classId}`, async () =>
classUserFRequest(API_BASE_URL, classId)
)
classUserFRequest(API_BASE_URL, classId),
),
);
else promises.push(Promise.resolve([0]));
if (adminId !== "")
promises.push(
props.dengi_cash.withCacheAsync(`adminfr-${adminId}`, async () =>
AdminUserFRequest(API_BASE_URL, adminId)
)
AdminUserFRequest(API_BASE_URL, adminId),
),
);
else promises.push(Promise.resolve([0]));
Promise.all(promises).then(([classRes, adminRes]) => {
@@ -79,9 +81,12 @@ export default function EditorPage(props) {
props.dengi_cash.delete(
"editor_schedule",
"editor_changes",
"editor_rings"
"editor_rings",
);
}, []); // clean on full rerender
const { trigger } = useWebHaptics();
// tabs
const tabs = [
[
@@ -189,7 +194,7 @@ export default function EditorPage(props) {
"flex items-center gap-2 transition-colors " +
ifstyle(
selectedTab == 2,
"text-transparent pointer-events-none select-none"
"text-transparent pointer-events-none select-none",
)
}
>
@@ -238,6 +243,7 @@ export default function EditorPage(props) {
key={idx}
onClick={() => {
if (selectedTab == idx) return;
trigger([{ duration: 35 }], { intensity: 1 });
if (!changesWereMade) {
selectTab(idx);
} else {