bug fixes
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"tailwindcss": "^4.1.12",
|
"tailwindcss": "^4.1.12",
|
||||||
|
"use-debounce": "^10.0.6",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.33.0",
|
"@eslint/js": "^9.33.0",
|
||||||
@@ -1135,6 +1136,8 @@
|
|||||||
|
|
||||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
"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=="],
|
"utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
|
||||||
|
|
||||||
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
||||||
|
|||||||
+17
@@ -64,6 +64,15 @@
|
|||||||
div[data-ktkz-loading] img {
|
div[data-ktkz-loading] img {
|
||||||
animation: ktkz-preloader-pulse 3s var(--animate-ease) infinite;
|
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 {
|
@keyframes ktkz-preloader-spin {
|
||||||
to {
|
to {
|
||||||
@@ -74,9 +83,11 @@
|
|||||||
from,
|
from,
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
transform: scale(100%);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
|
transform: scale(98%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@keyframes ktkz-preloader-show {
|
@keyframes ktkz-preloader-show {
|
||||||
@@ -93,6 +104,12 @@
|
|||||||
<div class="cont">
|
<div class="cont">
|
||||||
<img src="./src/assets/logo.svg" width="150" alt="" />
|
<img src="./src/assets/logo.svg" width="150" alt="" />
|
||||||
<div class="spinner" aria-hidden="true"></div>
|
<div class="spinner" aria-hidden="true"></div>
|
||||||
|
<p>
|
||||||
|
если не работает попробуйте
|
||||||
|
<a href="#" onclick="event.preventDefault();location.reload()"
|
||||||
|
>перезагрузить</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-1
@@ -20,7 +20,8 @@
|
|||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"tailwindcss": "^4.1.12"
|
"tailwindcss": "^4.1.12",
|
||||||
|
"use-debounce": "^10.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.33.0",
|
"@eslint/js": "^9.33.0",
|
||||||
|
|||||||
+263
-239
@@ -19,7 +19,7 @@ import {
|
|||||||
classUserFRequest,
|
classUserFRequest,
|
||||||
RaspGet,
|
RaspGet,
|
||||||
} from "../trash/req_mgr";
|
} from "../trash/req_mgr";
|
||||||
import { AnimatePresence, motion } from "motion/react";
|
import { AnimatePresence, LayoutGroup, motion } from "motion/react";
|
||||||
|
|
||||||
import { apiFormatDate, isTimeBeforeNow } from "../trash/dengi";
|
import { apiFormatDate, isTimeBeforeNow } from "../trash/dengi";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
@@ -90,7 +90,6 @@ export function DX4App({
|
|||||||
class: false,
|
class: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [classLinkCopied, setClassLinkCopied] = useState(false);
|
|
||||||
const lessonsEndedTriggered = useRef(false);
|
const lessonsEndedTriggered = useRef(false);
|
||||||
|
|
||||||
//TODO: Auto change day v2
|
//TODO: Auto change day v2
|
||||||
@@ -151,6 +150,37 @@ export function DX4App({
|
|||||||
})();
|
})();
|
||||||
}, [classId, adminId]);
|
}, [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 === "") {
|
if (classId === "") {
|
||||||
setsetRoute(setRoute, "/");
|
setsetRoute(setRoute, "/");
|
||||||
}
|
}
|
||||||
@@ -167,7 +197,6 @@ export function DX4App({
|
|||||||
"flex items-center w-full justify-between px-5" +
|
"flex items-center w-full justify-between px-5" +
|
||||||
ifstyle(openUserSettings, " pt-5")
|
ifstyle(openUserSettings, " pt-5")
|
||||||
}
|
}
|
||||||
layout="position"
|
|
||||||
>
|
>
|
||||||
<motion.img
|
<motion.img
|
||||||
src={Logo}
|
src={Logo}
|
||||||
@@ -214,6 +243,235 @@ export function DX4App({
|
|||||||
/>
|
/>
|
||||||
</motion.span>
|
</motion.span>
|
||||||
<AnimatePresence mode="popLayout">
|
<AnimatePresence mode="popLayout">
|
||||||
|
<UserSettings
|
||||||
|
{...{
|
||||||
|
openUserSettings,
|
||||||
|
userFrNames,
|
||||||
|
setUserId,
|
||||||
|
setsetRoute,
|
||||||
|
setRoute,
|
||||||
|
adminId,
|
||||||
|
classId,
|
||||||
|
pickmeMode,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</AnimatePresence>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
layout="position"
|
||||||
|
className="flex flex-col gap-5 w-full not-md:px-4"
|
||||||
|
>
|
||||||
|
{adminId != "" && (
|
||||||
|
<motion.div className="flex w-full justify-end">
|
||||||
|
<a
|
||||||
|
// onClick={() => {
|
||||||
|
// 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"
|
||||||
|
>
|
||||||
|
<BiPencil /> открыть в редакторе
|
||||||
|
</a>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
<DatePicker
|
||||||
|
date={selectedDate}
|
||||||
|
setDate={setSelectedDate}
|
||||||
|
indicator={typeof rasp[2] == "number" && [1, 2].includes(rasp[2])}
|
||||||
|
/>
|
||||||
|
<div className="relative">
|
||||||
|
<LayoutGroup>
|
||||||
|
<RaspView {...{ rasp, pickmeMode, selectedDate }} />
|
||||||
|
</LayoutGroup>
|
||||||
|
{!rasp[0] && (
|
||||||
|
<motion.div
|
||||||
|
className="w-full flex justify-center"
|
||||||
|
initial="hid"
|
||||||
|
animate="show"
|
||||||
|
variants={{
|
||||||
|
show: { opacity: 1, scale: 1 },
|
||||||
|
hid: { opacity: 0, scale: 0 },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LoadingSpinner size={25} />
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
<CoolMainBg {...{ pickmeMode }} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const CoolMainBg = React.memo(({ pickmeMode }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`fixed top-0 left-0 w-full h-full -z-5 overflow-hidden bg-gradient-to-br to-black to-50% bg-fixed
|
||||||
|
${pickmeMode ? "from-pink-400/10" : "from-white/2"}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const RaspView = React.memo(({ rasp, pickmeMode, selectedDate }) => {
|
||||||
|
return (
|
||||||
|
<AnimatePresence mode="popLayout">
|
||||||
|
{rasp[0] && typeof rasp[1] == "object" && (
|
||||||
|
<motion.table
|
||||||
|
//layoutId="schedule_table"
|
||||||
|
//layout="position"
|
||||||
|
key={selectedDate}
|
||||||
|
className={
|
||||||
|
"w-full border-collapse border-spacing-x-0 border-spacing-y-[10px] bg-gradient-to-br backdrop-blur-xl mb-10 " +
|
||||||
|
(pickmeMode ? "from-pink-400/30" : "from-zinc-800/40") +
|
||||||
|
" to-transparent rounded-2xl selectable"
|
||||||
|
}
|
||||||
|
variants={{
|
||||||
|
hid: { opacity: 0 },
|
||||||
|
show: { opacity: 1 },
|
||||||
|
}}
|
||||||
|
initial="hid"
|
||||||
|
animate="show"
|
||||||
|
exit="hid"
|
||||||
|
>
|
||||||
|
<thead className="">
|
||||||
|
<tr className=" *:text-center text-zinc-400 *:py-2 border-b *:my-5 *:min-w-15 *:lg:hover:text-zinc-200 *:transition-colors *:font-light">
|
||||||
|
<th
|
||||||
|
className="max-w-10"
|
||||||
|
//layout="position"
|
||||||
|
//layoutId="table-num-h"
|
||||||
|
>
|
||||||
|
n урока
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
//layout="position"
|
||||||
|
//layoutId="table-subj-h"
|
||||||
|
>
|
||||||
|
предмет
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
//layout="position"
|
||||||
|
//layoutId="table-cab-h"
|
||||||
|
>
|
||||||
|
каб
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
//layout="position"
|
||||||
|
//layoutId="table-t-h"
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-center gap-2">
|
||||||
|
{rasp[2] == 2 && (
|
||||||
|
<span className="w-2 h-2 animate-pulse rounded-full bg-zinc-300 block" />
|
||||||
|
)}
|
||||||
|
время
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="*:*:text-center *:*:py-2 *:not-last:border-b *:not-last:border-zinc-800 text-white">
|
||||||
|
{rasp[1].map((d, i) => (
|
||||||
|
<tr
|
||||||
|
//layout="position"
|
||||||
|
key={`table-header-${i}`}
|
||||||
|
className="transition-colors *:transition-colors lg:hover:bg-zinc-300/15"
|
||||||
|
//rasp-key={"rasp_key_" + i + Array(d).join()}
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
//layout="position"
|
||||||
|
//layoutId={`table-num-${i}`}
|
||||||
|
>
|
||||||
|
{d["num"]}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
//layout="position"
|
||||||
|
//layoutId={`table-subj-${i}`}
|
||||||
|
>
|
||||||
|
{d.subject
|
||||||
|
.toString()
|
||||||
|
.split("\n")
|
||||||
|
.map((line, i, array) => (
|
||||||
|
<React.Fragment key={i}>
|
||||||
|
{line}
|
||||||
|
{i < array.length - 1 && <br />}
|
||||||
|
</React.Fragment>
|
||||||
|
)) || d.subject}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
//layout="position"
|
||||||
|
//layoutId={`table-cab-${i}`}
|
||||||
|
>
|
||||||
|
{d.cabinet
|
||||||
|
.toString()
|
||||||
|
.split("\n")
|
||||||
|
.map((line, i, array) => (
|
||||||
|
<React.Fragment key={i}>
|
||||||
|
{line}
|
||||||
|
{i < array.length - 1 && <br />}
|
||||||
|
</React.Fragment>
|
||||||
|
)) || d.cabinet}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div
|
||||||
|
//layout="position"
|
||||||
|
//layoutId={`table-time-${i}`}
|
||||||
|
className="flex items-center justify-center min-h-9"
|
||||||
|
>
|
||||||
|
<div className="flex gap-0.5 flex-col *:block w-[70%] *:font-light">
|
||||||
|
<span className="text-left">
|
||||||
|
{d["t-begin"]} -
|
||||||
|
</span>
|
||||||
|
<span className="text-right">{d["t-end"]}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</motion.table>
|
||||||
|
)}
|
||||||
|
{typeof rasp[1] == "number" && rasp[1] === -322 && (
|
||||||
|
<motion.div
|
||||||
|
className="w-full flex justify-center"
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
>
|
||||||
|
<span className="text-2xl font-bold">нет уроков</span>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
{typeof rasp[1] == "string" && rasp[1].startsWith("ошибка") && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
className="w-full flex justify-center"
|
||||||
|
>
|
||||||
|
<span className="text-xl text-center text-transparent bg-clip-text bg-gradient-to-r from-red-300 to-red-500">
|
||||||
|
{rasp[1]}
|
||||||
|
</span>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const UserSettings = React.memo(
|
||||||
|
({
|
||||||
|
openUserSettings,
|
||||||
|
userFrNames,
|
||||||
|
setUserId,
|
||||||
|
setsetRoute,
|
||||||
|
setRoute,
|
||||||
|
adminId,
|
||||||
|
classId,
|
||||||
|
pickmeMode,
|
||||||
|
}) => {
|
||||||
|
const [classLinkCopied, setClassLinkCopied] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
{openUserSettings && (
|
{openUserSettings && (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="flex flex-col bg-grain gap-2 bg-zinc-700/20 p-2 rounded-2xl"
|
className="flex flex-col bg-grain gap-2 bg-zinc-700/20 p-2 rounded-2xl"
|
||||||
@@ -260,10 +518,7 @@ export function DX4App({
|
|||||||
classLinkCopied ? "скопированно" : "коп. ссылку",
|
classLinkCopied ? "скопированно" : "коп. ссылку",
|
||||||
() => {
|
() => {
|
||||||
copyToClipboard(
|
copyToClipboard(
|
||||||
location.href.substring(
|
location.href.substring(0, location.href.search("#")) +
|
||||||
0,
|
|
||||||
location.href.search("#")
|
|
||||||
) +
|
|
||||||
"#//" +
|
"#//" +
|
||||||
classId
|
classId
|
||||||
).then((a) => {
|
).then((a) => {
|
||||||
@@ -297,238 +552,7 @@ export function DX4App({
|
|||||||
)}
|
)}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
|
||||||
</motion.div>
|
|
||||||
</motion.div>
|
|
||||||
{adminId != "" && (
|
|
||||||
<motion.div
|
|
||||||
layout="position"
|
|
||||||
className="flex w-full justify-end px-5"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
// onClick={() => {
|
|
||||||
// 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"
|
|
||||||
>
|
|
||||||
<BiPencil /> открыть в редакторе
|
|
||||||
</a>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
<motion.div
|
|
||||||
layout="position"
|
|
||||||
className="flex flex-col gap-5 w-full not-md:px-4"
|
|
||||||
>
|
|
||||||
<DatePicker
|
|
||||||
date={selectedDate}
|
|
||||||
setDate={setSelectedDate}
|
|
||||||
indicator={typeof rasp[2] == "number" && [1, 2].includes(rasp[2])}
|
|
||||||
/>
|
|
||||||
<RaspView {...{ rasp, pickmeMode, selectedDate }} />
|
|
||||||
<AnimatePresence mode="popLayout">
|
|
||||||
{!rasp[0] && (
|
|
||||||
<motion.div
|
|
||||||
className="w-full flex justify-center"
|
|
||||||
initial="hid"
|
|
||||||
animate="show"
|
|
||||||
exit="hid"
|
|
||||||
variants={{
|
|
||||||
show: { opacity: 1, scale: 1 },
|
|
||||||
hid: { opacity: 0, scale: 0 },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<LoadingSpinner size={25} />
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
|
||||||
</motion.div>
|
|
||||||
</motion.div>
|
|
||||||
{/* <CoolMouseBg /> */}
|
|
||||||
</motion.div>
|
|
||||||
<CoolMainBg {...{ pickmeMode }} />
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
function CoolMainBg({ pickmeMode }) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`fixed top-0 left-0 w-full h-full -z-5 overflow-hidden bg-gradient-to-br to-black to-50% bg-fixed
|
|
||||||
${pickmeMode ? "from-pink-400/10" : "from-white/2"}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function RaspView({ rasp, pickmeMode, selectedDate }) {
|
|
||||||
const [tableColHover, setTableColHover] = useState(-1);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AnimatePresence mode="popLayout">
|
|
||||||
{rasp[0] && typeof rasp[1] == "object" && (
|
|
||||||
<motion.table
|
|
||||||
//layoutId="schedule_table"
|
|
||||||
//layout="position"
|
|
||||||
key={selectedDate}
|
|
||||||
className={
|
|
||||||
"w-full border-collapse border-spacing-x-0 border-spacing-y-[10px] bg-gradient-to-br backdrop-blur-xl mb-10 " +
|
|
||||||
(pickmeMode ? "from-pink-400/30" : "from-zinc-800/40") +
|
|
||||||
" to-transparent rounded-2xl selectable"
|
|
||||||
}
|
}
|
||||||
variants={{
|
);
|
||||||
hid: { opacity: 0 },
|
|
||||||
show: { opacity: 1 },
|
|
||||||
}}
|
|
||||||
initial="hid"
|
|
||||||
animate="show"
|
|
||||||
exit="hid"
|
|
||||||
>
|
|
||||||
<thead className="">
|
|
||||||
<tr className=" *:text-center text-zinc-400 *:py-2 border-b *:my-5 *:min-w-15 *:lg:hover:text-zinc-200 *:transition-colors *:font-light">
|
|
||||||
<th
|
|
||||||
className="max-w-10"
|
|
||||||
//layout="position"
|
|
||||||
//layoutId="table-num-h"
|
|
||||||
onMouseEnter={() => {
|
|
||||||
setTableColHover(0);
|
|
||||||
}}
|
|
||||||
onMouseLeave={() => {
|
|
||||||
setTableColHover(-1);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
n урока
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
//layout="position"
|
|
||||||
//layoutId="table-subj-h"
|
|
||||||
onMouseEnter={() => {
|
|
||||||
setTableColHover(1);
|
|
||||||
}}
|
|
||||||
onMouseLeave={() => {
|
|
||||||
setTableColHover(-1);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
предмет
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
//layout="position"
|
|
||||||
//layoutId="table-cab-h"
|
|
||||||
onMouseEnter={() => {
|
|
||||||
setTableColHover(2);
|
|
||||||
}}
|
|
||||||
onMouseLeave={() => {
|
|
||||||
setTableColHover(-1);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
каб
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
//layout="position"
|
|
||||||
//layoutId="table-t-h"
|
|
||||||
onMouseEnter={() => {
|
|
||||||
setTableColHover(3);
|
|
||||||
}}
|
|
||||||
onMouseLeave={() => {
|
|
||||||
setTableColHover(-1);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex items-center justify-center gap-2">
|
|
||||||
{rasp[2] == 2 && (
|
|
||||||
<span className="w-2 h-2 animate-pulse rounded-full bg-zinc-300 block" />
|
|
||||||
)}
|
|
||||||
время
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody className="*:*:text-center *:*:py-2 *:not-last:border-b *:not-last:border-zinc-800 text-white">
|
|
||||||
{rasp[1].map((d, i) => (
|
|
||||||
<tr
|
|
||||||
//layout="position"
|
|
||||||
key={`table-header-${i}`}
|
|
||||||
className="transition-colors *:transition-colors lg:hover:bg-zinc-300/15"
|
|
||||||
//rasp-key={"rasp_key_" + i + Array(d).join()}
|
|
||||||
>
|
|
||||||
<td
|
|
||||||
className={
|
|
||||||
(tableColHover == 0 ? "lg:bg-zinc-300/15" : "") +
|
|
||||||
" font-bold"
|
|
||||||
}
|
|
||||||
//layout="position"
|
|
||||||
//layoutId={`table-num-${i}`}
|
|
||||||
>
|
|
||||||
{d["num"]}
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
className={tableColHover == 1 ? "lg:bg-zinc-300/15" : ""}
|
|
||||||
//layout="position"
|
|
||||||
//layoutId={`table-subj-${i}`}
|
|
||||||
>
|
|
||||||
{d.subject
|
|
||||||
.toString()
|
|
||||||
.split("\n")
|
|
||||||
.map((line, i, array) => (
|
|
||||||
<React.Fragment key={i}>
|
|
||||||
{line}
|
|
||||||
{i < array.length - 1 && <br />}
|
|
||||||
</React.Fragment>
|
|
||||||
)) || d.subject}
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
//layout="position"
|
|
||||||
//layoutId={`table-cab-${i}`}
|
|
||||||
className={tableColHover == 2 ? "lg:bg-zinc-300/15" : ""}
|
|
||||||
>
|
|
||||||
{d.cabinet
|
|
||||||
.toString()
|
|
||||||
.split("\n")
|
|
||||||
.map((line, i, array) => (
|
|
||||||
<React.Fragment key={i}>
|
|
||||||
{line}
|
|
||||||
{i < array.length - 1 && <br />}
|
|
||||||
</React.Fragment>
|
|
||||||
)) || d.cabinet}
|
|
||||||
</td>
|
|
||||||
<td className={tableColHover == 3 ? "lg:bg-zinc-300/15" : ""}>
|
|
||||||
<div
|
|
||||||
//layout="position"
|
|
||||||
//layoutId={`table-time-${i}`}
|
|
||||||
className="flex items-center justify-center min-h-9"
|
|
||||||
>
|
|
||||||
<div className="flex gap-0.5 flex-col *:block w-[70%] *:font-light">
|
|
||||||
<span className="text-left">
|
|
||||||
{d["t-begin"]} -
|
|
||||||
</span>
|
|
||||||
<span className="text-right">{d["t-end"]}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</motion.table>
|
|
||||||
)}
|
|
||||||
{typeof rasp[1] == "number" && rasp[1] === -322 && (
|
|
||||||
<motion.div
|
|
||||||
className="w-full flex justify-center"
|
|
||||||
initial={{ opacity: 0, y: 10 }}
|
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
exit={{ opacity: 0, x: 10 }}
|
|
||||||
>
|
|
||||||
<span className="text-2xl font-bold">нет уроков</span>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
{typeof rasp[1] == "string" && rasp[1].startsWith("ошибка") && (
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0, y: 10 }}
|
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
exit={{ opacity: 0, x: 10 }}
|
|
||||||
className="w-full flex justify-center"
|
|
||||||
>
|
|
||||||
<span className="text-xl text-center text-transparent bg-clip-text bg-gradient-to-r from-red-300 to-red-500">
|
|
||||||
{rasp[1]}
|
|
||||||
</span>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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 { BiCheck, BiLeftArrowAlt, BiRightArrowAlt, BiX } from "react-icons/bi";
|
||||||
import { formatDate, getDateTags } from "./dengi.js";
|
import { formatDate, getDateTags } from "./dengi.js";
|
||||||
import { AnimatePresence, motion } from "motion/react";
|
import { AnimatePresence, motion, LayoutGroup } from "motion/react";
|
||||||
|
|
||||||
export function Switch({
|
export function Switch({
|
||||||
checked,
|
checked,
|
||||||
@@ -105,11 +105,12 @@ function DatePickerButton({ next = false, date, setDate }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DatePicker(props) {
|
export const DatePicker = React.memo((props) => {
|
||||||
const dateTag = getDateTags(props.date);
|
const dateTag = getDateTags(props.date);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between px-2 py-1 w-full bg-grain border-zinc-800/40 border rounded-2xl">
|
<LayoutGroup>
|
||||||
|
<div className="flex items-center justify-between px-2 py-1 w-full bg-grain border-zinc-800/40 border rounded-2xl relative">
|
||||||
<DatePickerButton date={props.date} setDate={props.setDate} />
|
<DatePickerButton date={props.date} setDate={props.setDate} />
|
||||||
<AnimatePresence mode="popLayout">
|
<AnimatePresence mode="popLayout">
|
||||||
<motion.span
|
<motion.span
|
||||||
@@ -166,8 +167,9 @@ export function DatePicker(props) {
|
|||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
<DatePickerButton next date={props.date} setDate={props.setDate} />
|
<DatePickerButton next date={props.date} setDate={props.setDate} />
|
||||||
</div>
|
</div>
|
||||||
|
</LayoutGroup>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
export function DengiButton({
|
export function DengiButton({
|
||||||
onClick,
|
onClick,
|
||||||
|
|||||||
+4
-4
@@ -5,17 +5,17 @@ import { VitePWA } from "vite-plugin-pwa";
|
|||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
base:"/dx4/",
|
base: "/dx4/",
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
tailwindcss(),
|
tailwindcss(),
|
||||||
VitePWA({
|
VitePWA({
|
||||||
registerType: "autoUpdate",
|
registerType: "autoUpdate",
|
||||||
manifest: {
|
manifest: {
|
||||||
name: "dnevnik-x 4",
|
name: "dx 4",
|
||||||
short_name: "dx4",
|
short_name: "dx4",
|
||||||
description: "",
|
description: "dnevnik-x app",
|
||||||
theme_color: "#000",
|
theme_color: "#eee",
|
||||||
background_color: "#000",
|
background_color: "#000",
|
||||||
display: "standalone",
|
display: "standalone",
|
||||||
scope: "/dx4/",
|
scope: "/dx4/",
|
||||||
|
|||||||
Reference in New Issue
Block a user