diff --git a/bun.lock b/bun.lock index f3e73df..f539f76 100644 --- a/bun.lock +++ b/bun.lock @@ -15,6 +15,7 @@ "react-dom": "^19.1.1", "react-icons": "^5.5.0", "tailwindcss": "^4.1.12", + "use-debounce": "^10.0.6", }, "devDependencies": { "@eslint/js": "^9.33.0", @@ -1135,6 +1136,8 @@ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "use-debounce": ["use-debounce@10.0.6", "", { "peerDependencies": { "react": "*" } }, "sha512-C5OtPyhAZgVoteO9heXMTdW7v/IbFI+8bSVKYCJrSmiWWCLsbUxiBSp4t9v0hNBTGY97bT72ydDIDyGSFWfwXg=="], + "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], diff --git a/index.html b/index.html index 89f71c7..7cf409d 100644 --- a/index.html +++ b/index.html @@ -64,6 +64,15 @@ div[data-ktkz-loading] img { animation: ktkz-preloader-pulse 3s var(--animate-ease) infinite; } + div[data-ktkz-loading] p { + font-family: "Segoe UI", sans-serif; + color: #eef; + opacity: 0; + animation: ktkz-preloader-show 2s linear 2s forwards; + } + div[data-ktkz-loading] p a { + color: #aaf; + } @keyframes ktkz-preloader-spin { to { @@ -74,9 +83,11 @@ from, to { opacity: 1; + transform: scale(100%); } 50% { opacity: 0.3; + transform: scale(98%); } } @keyframes ktkz-preloader-show { @@ -93,6 +104,12 @@
+

+ если не работает попробуйте + перезагрузить +

diff --git a/package.json b/package.json index 989fdad..dfe2df0 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "react": "^19.1.1", "react-dom": "^19.1.1", "react-icons": "^5.5.0", - "tailwindcss": "^4.1.12" + "tailwindcss": "^4.1.12", + "use-debounce": "^10.0.6" }, "devDependencies": { "@eslint/js": "^9.33.0", diff --git a/src/pages/DX4AppPage.jsx b/src/pages/DX4AppPage.jsx index b41d51e..b256ef0 100644 --- a/src/pages/DX4AppPage.jsx +++ b/src/pages/DX4AppPage.jsx @@ -19,7 +19,7 @@ import { classUserFRequest, RaspGet, } from "../trash/req_mgr"; -import { AnimatePresence, motion } from "motion/react"; +import { AnimatePresence, LayoutGroup, motion } from "motion/react"; import { apiFormatDate, isTimeBeforeNow } from "../trash/dengi"; import { useAtom } from "jotai"; @@ -90,7 +90,6 @@ export function DX4App({ class: false, }); - const [classLinkCopied, setClassLinkCopied] = useState(false); const lessonsEndedTriggered = useRef(false); //TODO: Auto change day v2 @@ -151,6 +150,37 @@ export function DX4App({ })(); }, [classId, adminId]); + const handleKeyPress = (event) => { + switch (event.key) { + case "a": + case "ArrowLeft": + setSelectedDate((prevDate) => { + const newDate = new Date(prevDate); + newDate.setDate(newDate.getDate() - 1); + return newDate; + }); + break; + case "d": + case "ArrowRight": + setSelectedDate((prevDate) => { + const newDate = new Date(prevDate); + newDate.setDate(newDate.getDate() + 1); + return newDate; + }); + break; + default: + break; + } + }; + + useEffect(() => { + window.addEventListener("keydown", handleKeyPress); + + return () => { + window.removeEventListener("keydown", handleKeyPress); + }; + }, []); + if (classId === "") { setsetRoute(setRoute, "/"); } @@ -167,7 +197,6 @@ export function DX4App({ "flex items-center w-full justify-between px-5" + ifstyle(openUserSettings, " pt-5") } - layout="position" > - {openUserSettings && ( - - {[ - // icon - // text - // onclick - // condition - [ - , - "выход", - () => { - setUserId(""); - setsetRoute(setRoute, "/"); - }, - true, - ], - // [ - // , - // "пикми режим", - // () => { - // setPickmeMode(!pickmeMode); - // }, - // true, - // ], - [ - , - `админ ${ - userFrNames["admin"] ? userFrNames["admin"] : adminId - }`, - () => {}, - adminId != "", - ], - [ - , - classLinkCopied ? "скопированно" : "коп. ссылку", - () => { - copyToClipboard( - location.href.substring( - 0, - location.href.search("#") - ) + - "#//" + - classId - ).then((a) => { - if (a) { - setClassLinkCopied(true); - setTimeout(() => { - setClassLinkCopied(false); - }, 2000); - } - }); - }, - classId != "", - ], - ].map( - (item, i) => - item[3] && ( -
- {item[0]} {item[1]} -
- ) - )} -
- )} +
- {adminId != "" && ( - - { - // setsetRoute(setRoute, `/editor/${apiFormatDate(selectedDate)}`); - // }} - href={`#/editor/${apiFormatDate(selectedDate)}`} - className="flex items-center justify-center border p-1 gap-2 px-2 lg:hover:border-white cursor-pointer rounded-xl transition-colors border-zinc-700 text-zinc-400 lg:hover:text-white" - > - открыть в редакторе - - - )} + + {adminId != "" && ( + + { + // setsetRoute(setRoute, `/editor/${apiFormatDate(selectedDate)}`); + // }} + href={`#/editor/${apiFormatDate(selectedDate)}`} + className="flex items-center justify-center border p-1 gap-2 px-2 lg:hover:border-white cursor-pointer rounded-xl transition-colors border-zinc-700 text-zinc-400 lg:hover:text-white" + > + открыть в редакторе + + + )} - - +
+ + + {!rasp[0] && ( )} - +
- {/* */} ); } -function CoolMainBg({ pickmeMode }) { +const CoolMainBg = React.memo(({ pickmeMode }) => { return (
); -} - -export function RaspView({ rasp, pickmeMode, selectedDate }) { - const [tableColHover, setTableColHover] = useState(-1); +}); +export const RaspView = React.memo(({ rasp, pickmeMode, selectedDate }) => { return ( {rasp[0] && typeof rasp[1] == "object" && ( @@ -388,48 +342,24 @@ export function RaspView({ rasp, pickmeMode, selectedDate }) { className="max-w-10" //layout="position" //layoutId="table-num-h" - onMouseEnter={() => { - setTableColHover(0); - }} - onMouseLeave={() => { - setTableColHover(-1); - }} > n урока { - setTableColHover(1); - }} - onMouseLeave={() => { - setTableColHover(-1); - }} + //layout="position" + //layoutId="table-subj-h" > предмет { - setTableColHover(2); - }} - onMouseLeave={() => { - setTableColHover(-1); - }} + //layout="position" + //layoutId="table-cab-h" > каб { - setTableColHover(3); - }} - onMouseLeave={() => { - setTableColHover(-1); - }} + //layout="position" + //layoutId="table-t-h" >
{rasp[2] == 2 && ( @@ -449,19 +379,14 @@ export function RaspView({ rasp, pickmeMode, selectedDate }) { //rasp-key={"rasp_key_" + i + Array(d).join()} > {d["num"]} {d.subject .toString() @@ -474,9 +399,8 @@ export function RaspView({ rasp, pickmeMode, selectedDate }) { )) || d.subject} {d.cabinet .toString() @@ -488,7 +412,7 @@ export function RaspView({ rasp, pickmeMode, selectedDate }) { )) || d.cabinet} - +
нет уроков )} {typeof rasp[1] == "string" && rasp[1].startsWith("ошибка") && ( @@ -531,4 +455,104 @@ export function RaspView({ rasp, pickmeMode, selectedDate }) { )} ); -} +}); + +const UserSettings = React.memo( + ({ + openUserSettings, + userFrNames, + setUserId, + setsetRoute, + setRoute, + adminId, + classId, + pickmeMode, + }) => { + const [classLinkCopied, setClassLinkCopied] = useState(false); + + return ( + <> + {openUserSettings && ( + + {[ + // icon + // text + // onclick + // condition + [ + , + "выход", + () => { + setUserId(""); + setsetRoute(setRoute, "/"); + }, + true, + ], + // [ + // , + // "пикми режим", + // () => { + // setPickmeMode(!pickmeMode); + // }, + // true, + // ], + [ + , + `админ ${ + userFrNames["admin"] ? userFrNames["admin"] : adminId + }`, + () => {}, + adminId != "", + ], + [ + , + classLinkCopied ? "скопированно" : "коп. ссылку", + () => { + copyToClipboard( + location.href.substring(0, location.href.search("#")) + + "#//" + + classId + ).then((a) => { + if (a) { + setClassLinkCopied(true); + setTimeout(() => { + setClassLinkCopied(false); + }, 2000); + } + }); + }, + classId != "", + ], + ].map( + (item, i) => + item[3] && ( +
+ {item[0]} {item[1]} +
+ ) + )} +
+ )} + + ); + } +); diff --git a/src/trash/trash-components.jsx b/src/trash/trash-components.jsx index b284e2d..5741118 100644 --- a/src/trash/trash-components.jsx +++ b/src/trash/trash-components.jsx @@ -1,7 +1,7 @@ -import { useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import { BiCheck, BiLeftArrowAlt, BiRightArrowAlt, BiX } from "react-icons/bi"; import { formatDate, getDateTags } from "./dengi.js"; -import { AnimatePresence, motion } from "motion/react"; +import { AnimatePresence, motion, LayoutGroup } from "motion/react"; export function Switch({ checked, @@ -105,69 +105,71 @@ function DatePickerButton({ next = false, date, setDate }) { ); } -export function DatePicker(props) { +export const DatePicker = React.memo((props) => { const dateTag = getDateTags(props.date); return ( -
- - - { - props.setDate(new Date()); - }} - > + +
+ + - { + props.setDate(new Date()); + }} > - {formatDate(props.date)} + + + {formatDate(props.date)} + + {dateTag.length > 0 && ( + <> + + + + + {dateTag} + + + )} - {dateTag.length > 0 && ( - <> - - - - - {dateTag} - - - )} - - - -
+
+ +
+ ); -} +}); export function DengiButton({ onClick, diff --git a/vite.config.js b/vite.config.js index 83d28c2..36d3fc0 100644 --- a/vite.config.js +++ b/vite.config.js @@ -5,17 +5,17 @@ import { VitePWA } from "vite-plugin-pwa"; // https://vite.dev/config/ export default defineConfig({ - base:"/dx4/", + base: "/dx4/", plugins: [ react(), tailwindcss(), VitePWA({ registerType: "autoUpdate", manifest: { - name: "dnevnik-x 4", + name: "dx 4", short_name: "dx4", - description: "", - theme_color: "#000", + description: "dnevnik-x app", + theme_color: "#eee", background_color: "#000", display: "standalone", scope: "/dx4/",