관리자 페이지 교육과정 등록, 비밀번호 재설정 생성
This commit is contained in:
0
app/admin_home/page.tsx
Normal file
0
app/admin_home/page.tsx
Normal file
608
app/admin_lecture1/page.tsx
Normal file
608
app/admin_lecture1/page.tsx
Normal file
@@ -0,0 +1,608 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import Close from '../../public/svg/close';
|
||||||
|
|
||||||
|
const imgLogo = "http://localhost:3845/assets/89fda8e949171025b1232bae70fc9d442e4e70c8.png";
|
||||||
|
const imgArrowDisabled = "http://localhost:3845/assets/6edcb2defc36a2bf4a05a3abe53b8da3d42b2cb4.svg";
|
||||||
|
const imgArrowDefault = "http://localhost:3845/assets/ad0cb4418492f1b020bb38a2ff038a331294ce87.svg";
|
||||||
|
const imgArrowNext = "http://localhost:3845/assets/6328cf96ee1169c1425c2ce55e7a2dcca0374508.svg";
|
||||||
|
const imgLogout = "http://localhost:3845/assets/2277a58aa2f582fd42132439745c5bb051f322c2.svg";
|
||||||
|
const imgClose = "http://localhost:3845/assets/51206896b81ebe68b2d80b5b603e576227587007.svg";
|
||||||
|
const imgCloseX = "http://localhost:3845/assets/91a45a4f2e47cd854574f32ee6ac1b84e12807cf.svg";
|
||||||
|
const imgMingcuteDownLine = "http://localhost:3845/assets/a50ea05576e2bcccf052b5be6750edaf476ad4d4.svg";
|
||||||
|
|
||||||
|
interface Course {
|
||||||
|
id: number;
|
||||||
|
courseName: string;
|
||||||
|
instructorName: string;
|
||||||
|
isIncluded: string;
|
||||||
|
createdAt: string;
|
||||||
|
registrar: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type PaginationMove = "Previous" | "Next";
|
||||||
|
type PaginationStatus = "Default" | "Disabled";
|
||||||
|
|
||||||
|
function PaginationBtnMove({ status = "Default", move = "Previous" }: { status?: PaginationStatus; move?: PaginationMove }) {
|
||||||
|
const isDisabled = status === "Disabled";
|
||||||
|
const isNext = move === "Next";
|
||||||
|
|
||||||
|
if (isDisabled && isNext) {
|
||||||
|
// Disabled Next 버튼
|
||||||
|
return (
|
||||||
|
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px]">
|
||||||
|
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||||
|
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||||
|
<div className="flex-none rotate-[180deg]">
|
||||||
|
<div className="overflow-clip relative size-[20px]">
|
||||||
|
<div className="absolute flex inset-[15.63%_30.21%] items-center justify-center">
|
||||||
|
<div className="flex-none h-[16.5px] rotate-[180deg] w-[9.5px]">
|
||||||
|
<div className="relative size-full">
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
<img alt="" className="block max-w-none size-full" style={{ filter: 'opacity(0.88) brightness(0) saturate(100%) invert(88%)', opacity: 1 }} src={imgArrowNext} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDisabled && !isNext) {
|
||||||
|
// Disabled Previous 버튼
|
||||||
|
return (
|
||||||
|
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px]">
|
||||||
|
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||||
|
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||||
|
<div className="flex-none rotate-[180deg]">
|
||||||
|
<div className="overflow-clip relative size-[20px]">
|
||||||
|
<div className="absolute inset-[15.63%_30.21%]">
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
<img alt="" className="block max-w-none size-full" style={{ filter: 'opacity(0.88) brightness(0) saturate(100%) invert(88%)', opacity: 1 }} src={imgArrowDefault} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNext) {
|
||||||
|
// Default Next 버튼
|
||||||
|
return (
|
||||||
|
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||||
|
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||||
|
<div className="flex-none rotate-[180deg]">
|
||||||
|
<div className="overflow-clip relative size-[20px]">
|
||||||
|
<div className="absolute flex inset-[15.63%_30.21%] items-center justify-center">
|
||||||
|
<div className="flex-none h-[16.5px] rotate-[180deg] w-[9.5px]">
|
||||||
|
<div className="relative size-full">
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
<img alt="" className="block max-w-none size-full" src={imgArrowNext} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default Previous 버튼
|
||||||
|
return (
|
||||||
|
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||||
|
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||||
|
<div className="flex-none rotate-[180deg]">
|
||||||
|
<div className="overflow-clip relative size-[20px]">
|
||||||
|
<div className="absolute inset-[15.63%_30.21%]">
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
<img alt="" className="block max-w-none size-full" src={imgArrowDefault} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AdminLecture1Page() {
|
||||||
|
const router = useRouter();
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
const [courseName, setCourseName] = useState('');
|
||||||
|
const [instructorName, setInstructorName] = useState('');
|
||||||
|
const [showInstructorDropdown, setShowInstructorDropdown] = useState(false);
|
||||||
|
const [nextId, setNextId] = useState(14);
|
||||||
|
|
||||||
|
// 샘플 강좌 데이터
|
||||||
|
const [courses, setCourses] = useState<Course[]>([
|
||||||
|
{ id: 39, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 38, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 37, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 36, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 35, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 34, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 33, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 32, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 31, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 30, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 29, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 28, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 27, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 26, courseName: '방사선 원리', instructorName: '김강사', isIncluded: '포함', createdAt: '2025-12-11', registrar: '김등록' },
|
||||||
|
{ id: 25, courseName: '방사선 원리', instructorName: '김강사', isIncluded: '포함', createdAt: '2025-12-11', registrar: '김등록' },
|
||||||
|
{ id: 24, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 23, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 22, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 21, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 20, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 19, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 18, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 17, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 16, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 15, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 14, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 13, courseName: '방사선 원리', instructorName: '김강사', isIncluded: '포함', createdAt: '2025-12-11', registrar: '김등록' },
|
||||||
|
{ id: 12, courseName: '방사선 원리', instructorName: '김강사', isIncluded: '포함', createdAt: '2025-12-11', registrar: '김등록' },
|
||||||
|
{ id: 11, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 10, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 9, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 8, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 7, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 6, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 5, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 4, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 3, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 2, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
{ id: 1, courseName: '방사선 적용', instructorName: '김강사', isIncluded: '포함', createdAt: '2026-01-15', registrar: '이철수' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const instructors = ['김강사', '이강사', '박강사', '최강사'];
|
||||||
|
|
||||||
|
const handleOpenModal = () => {
|
||||||
|
setIsModalOpen(true);
|
||||||
|
setCourseName('');
|
||||||
|
setInstructorName('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseModal = () => {
|
||||||
|
setIsModalOpen(false);
|
||||||
|
setCourseName('');
|
||||||
|
setInstructorName('');
|
||||||
|
setShowInstructorDropdown(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
if (!courseName.trim() || !instructorName.trim()) {
|
||||||
|
alert('교육 과정명과 강사를 입력해 주세요.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
const formattedDate = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
|
||||||
|
|
||||||
|
const newCourse: Course = {
|
||||||
|
id: nextId,
|
||||||
|
courseName: courseName.trim(),
|
||||||
|
instructorName: instructorName.trim(),
|
||||||
|
isIncluded: '미포함',
|
||||||
|
createdAt: formattedDate,
|
||||||
|
registrar: '관리자',
|
||||||
|
};
|
||||||
|
|
||||||
|
const updatedCourses = [...courses, newCourse];
|
||||||
|
setCourses(updatedCourses);
|
||||||
|
setNextId(nextId + 1);
|
||||||
|
|
||||||
|
// 13개를 넘어가면 해당 페이지로 이동
|
||||||
|
const newTotalPages = Math.ceil(updatedCourses.length / 13);
|
||||||
|
if (newTotalPages > 1 && updatedCourses.length > 13) {
|
||||||
|
setCurrentPage(newTotalPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCloseModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectInstructor = (instructor: string) => {
|
||||||
|
setInstructorName(instructor);
|
||||||
|
setShowInstructorDropdown(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const itemsPerPage = 13;
|
||||||
|
const totalPages = Math.ceil(courses.length / itemsPerPage);
|
||||||
|
const pageNumbers = Array.from({ length: totalPages }, (_, i) => i + 1);
|
||||||
|
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||||
|
const endIndex = startIndex + itemsPerPage;
|
||||||
|
const currentCourses = courses.slice(startIndex, endIndex);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-white relative size-full min-h-screen">
|
||||||
|
{/* 사이드바 */}
|
||||||
|
<div className="absolute bg-white border-r border-[#eeeeee] border-solid box-border content-stretch flex flex-col gap-[45px] items-center left-0 min-h-[1080px] pb-8 pt-[30px] px-0 top-0 w-[250px]">
|
||||||
|
{/* 로고 */}
|
||||||
|
<button
|
||||||
|
onClick={() => router.push('/')}
|
||||||
|
className="h-[102px] relative shrink-0 w-[99px] cursor-pointer hover:opacity-80 transition-opacity"
|
||||||
|
>
|
||||||
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||||
|
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgLogo} />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{/* 메뉴 */}
|
||||||
|
<div className="box-border content-stretch flex flex-col items-center pb-0 pt-4 px-0 relative shrink-0 w-[250px]">
|
||||||
|
<div className="box-border content-stretch flex flex-col gap-2 items-start p-3 relative shrink-0 w-full">
|
||||||
|
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
권한 설정
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button className="bg-[#f7f7f7] box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
교육 과정 관리
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
강좌 관리
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
문제 은행 관리
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
수료증 발급
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
공지사항
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
학습 자료실
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
로그/접속 기록
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||||
|
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||||
|
배너 관리
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 로그아웃 */}
|
||||||
|
<div className="content-stretch flex gap-[9px] items-center relative shrink-0">
|
||||||
|
<div className="flex items-center justify-center relative shrink-0">
|
||||||
|
<div className="flex-none rotate-[180deg] scale-y-[-100%]">
|
||||||
|
<div className="h-[23.12px] relative w-[22px]">
|
||||||
|
<img alt="" className="block max-w-none size-full" src={imgLogout} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
localStorage.removeItem('isLoggedIn');
|
||||||
|
router.push('/');
|
||||||
|
}}
|
||||||
|
className="content-stretch flex h-[36px] items-center justify-between relative shrink-0 w-[76px] cursor-pointer hover:opacity-80 transition-opacity"
|
||||||
|
>
|
||||||
|
<div className="box-border content-stretch flex gap-[10px] items-center justify-center px-[10px] py-[5px] relative shrink-0">
|
||||||
|
<p className="font-medium leading-[1.6] not-italic relative shrink-0 text-[16px] text-[#404040] text-nowrap whitespace-pre">
|
||||||
|
로그아웃
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 메인 콘텐츠 */}
|
||||||
|
<div className="absolute left-[250px] top-0 right-0 min-h-screen">
|
||||||
|
{/* 헤더 */}
|
||||||
|
<div className="absolute content-stretch flex gap-[24px] items-center left-[48px] top-[45px]">
|
||||||
|
<div className="border-[#2b82e8] border-b-[2px] border-solid box-border content-stretch flex gap-[150px] items-center relative shrink-0">
|
||||||
|
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
|
||||||
|
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||||
|
교육 과정 관리
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 교육 과정 등록 버튼 */}
|
||||||
|
<button
|
||||||
|
onClick={handleOpenModal}
|
||||||
|
className="absolute bg-[#160e0e] box-border content-stretch flex gap-[10px] items-center justify-center right-[101px] p-[10px] rounded-[10px] top-[72px] w-[167px] cursor-pointer hover:bg-[#2a1f1f] transition-colors"
|
||||||
|
>
|
||||||
|
<p className="font-bold leading-[1.6] not-italic relative shrink-0 text-[18px] text-nowrap text-white whitespace-pre">
|
||||||
|
교육 과정 등록
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* 테이블 */}
|
||||||
|
<div className="absolute content-stretch flex flex-col items-start left-[48px] right-[101px] top-[186px] h-[671px] overflow-hidden">
|
||||||
|
{/* 테이블 헤더 */}
|
||||||
|
<div className="bg-[#f5fbff] content-stretch flex h-[41px] items-center relative shrink-0 w-full">
|
||||||
|
<div className="content-stretch flex items-center relative shrink-0 w-full">
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">교육 과정명</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">강사명</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">강좌 포함 여부</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">생성일</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">등록 담당자</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 테이블 바디 */}
|
||||||
|
<div className="content-stretch flex flex-col items-start relative shrink-0 w-full max-h-[630px] overflow-y-auto">
|
||||||
|
{currentCourses.map((course) => (
|
||||||
|
<div key={course.id} className="bg-white content-stretch flex items-center relative shrink-0 w-full">
|
||||||
|
<div className="content-stretch flex items-center relative shrink-0 w-full">
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">{course.courseName}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">{course.instructorName}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">{course.isIncluded}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">{course.createdAt}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 border-[0.5px_0.5px_0.5px_0px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||||
|
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||||
|
<p className="leading-[normal]">{course.registrar}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 페이지네이션 */}
|
||||||
|
<div className="absolute content-stretch flex gap-2 items-center justify-center left-[48px] right-[101px] top-[909px]">
|
||||||
|
<button onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}>
|
||||||
|
<PaginationBtnMove status={currentPage === 1 ? "Disabled" : "Default"} move="Previous" />
|
||||||
|
</button>
|
||||||
|
<div className="content-stretch flex gap-2 items-center relative shrink-0">
|
||||||
|
{pageNumbers.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCurrentPage(pageNum)}
|
||||||
|
className={`relative rounded-[8px] shrink-0 size-[30px] cursor-pointer transition-colors ${currentPage === pageNum
|
||||||
|
? 'bg-[#1d1d1d]'
|
||||||
|
: 'border border-[#eeeeee] border-solid hover:bg-gray-50'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||||
|
<div className={`absolute flex flex-col font-medium justify-center leading-[0] left-[15.5px] not-italic text-[14px] text-center text-nowrap top-[15px] translate-x-[-50%] translate-y-[-50%] ${currentPage === pageNum ? 'text-white' : 'text-[#515151]'
|
||||||
|
}`}>
|
||||||
|
<p className="leading-[1.6] whitespace-pre">{pageNum}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<button onClick={() => setCurrentPage(Math.min(totalPages, currentPage + 1))}>
|
||||||
|
<PaginationBtnMove status={currentPage === totalPages ? "Disabled" : "Default"} move="Next" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 모달 팝업 */}
|
||||||
|
{isModalOpen && (
|
||||||
|
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||||
|
{/* 배경 오버레이 */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 bg-[rgba(0,0,0,0.6)]"
|
||||||
|
onClick={handleCloseModal}
|
||||||
|
/>
|
||||||
|
{/* 모달 컨텐츠 */}
|
||||||
|
<div
|
||||||
|
className="relative bg-[#f7f7f7] h-[504px] overflow-clip shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] w-[683px]"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{/* 닫기 버튼 */}
|
||||||
|
<button
|
||||||
|
onClick={handleCloseModal}
|
||||||
|
className="absolute left-[622px] overflow-clip size-[30px] top-[41px] cursor-pointer hover:opacity-80 transition-opacity z-10"
|
||||||
|
>
|
||||||
|
<div className="absolute inset-0 pointer-events-none flex items-center justify-center">
|
||||||
|
<Close />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* 저장 버튼 */}
|
||||||
|
<button
|
||||||
|
onClick={handleSave}
|
||||||
|
className="absolute bg-[#599ded] box-border content-stretch flex gap-[10px] h-[50px] items-center justify-center left-[358px] p-[10px] rounded-[10px] top-[414px] w-[264px] cursor-pointer hover:bg-[#4a8ddc] transition-colors"
|
||||||
|
>
|
||||||
|
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[18px] text-nowrap text-white whitespace-pre">
|
||||||
|
저장
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* 취소 버튼 */}
|
||||||
|
<button
|
||||||
|
onClick={handleCloseModal}
|
||||||
|
className="absolute bg-[#eeeeee] box-border content-stretch flex gap-[10px] h-[50px] items-center justify-center left-[62px] p-[10px] rounded-[10px] top-[414px] w-[264px] cursor-pointer hover:bg-[#e0e0e0] transition-colors"
|
||||||
|
>
|
||||||
|
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||||
|
취소
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* 폼 컨텐츠 */}
|
||||||
|
<div className="absolute content-stretch flex flex-col gap-[20px] items-start left-[31px] top-[41px] w-[621px]">
|
||||||
|
<div className="content-stretch flex flex-col gap-[20px] items-start relative shrink-0 w-[621px]">
|
||||||
|
{/* 제목 */}
|
||||||
|
<div className="content-stretch flex gap-[10px] items-center relative shrink-0 w-full">
|
||||||
|
<div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[20px] text-[#404040] text-nowrap">
|
||||||
|
<p className="leading-[1.6] whitespace-pre">교육 과정 등록</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 교육 과정명 */}
|
||||||
|
<div className="content-stretch flex flex-col gap-[20px] items-start relative shrink-0 w-full">
|
||||||
|
<div className="content-stretch flex gap-[16px] items-center relative shrink-0 w-full">
|
||||||
|
<div className="content-stretch flex gap-[10px] items-center relative shrink-0 w-[177px]">
|
||||||
|
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||||
|
교육 과정명<span className="text-[#e61a1a]"> *</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={courseName}
|
||||||
|
onChange={(e) => setCourseName(e.target.value)}
|
||||||
|
placeholder="교육 과정명을 입력해 주세요."
|
||||||
|
className="basis-0 border border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center justify-center min-h-px min-w-px p-[10px] relative rounded-[8px] shrink-0 bg-white text-[16px] text-[#515151] focus:outline-none focus:border-[#2b82e8]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 강사 */}
|
||||||
|
<div className="content-stretch flex flex-col gap-[20px] items-start relative shrink-0 w-full">
|
||||||
|
<div className="content-stretch flex gap-[16px] items-center relative shrink-0 w-full">
|
||||||
|
<div className="content-stretch flex gap-[10px] items-center relative shrink-0 w-[177px]">
|
||||||
|
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||||
|
강사<span className="text-[#e61a1a]"> *</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="basis-0 relative grow min-h-px min-w-px shrink-0">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowInstructorDropdown(!showInstructorDropdown)}
|
||||||
|
className="basis-0 border border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center justify-between min-h-px min-w-px p-[10px] relative rounded-[8px] shrink-0 w-full bg-white cursor-pointer hover:border-[#2b82e8] transition-colors"
|
||||||
|
>
|
||||||
|
<p className={`basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic relative shrink-0 text-left text-[16px] ${instructorName ? 'text-[#515151]' : 'text-[#b9b9b9]'}`}>
|
||||||
|
{instructorName || '강사를 선택해 주세요.'}
|
||||||
|
</p>
|
||||||
|
<div className="overflow-clip relative shrink-0 size-[24px]">
|
||||||
|
<img alt="" className="block max-w-none size-full" src={imgMingcuteDownLine} />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{showInstructorDropdown && (
|
||||||
|
<div className="absolute top-full left-0 right-0 mt-1 bg-white box-border content-stretch flex flex-col gap-[4px] items-start p-[8px] rounded-[8px] shadow-[0px_8px_16px_-2px_rgba(27,33,44,0.12)] z-10">
|
||||||
|
{instructors.map((instructor) => (
|
||||||
|
<button
|
||||||
|
key={instructor}
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleSelectInstructor(instructor)}
|
||||||
|
className={`box-border content-stretch flex gap-[10px] h-[38px] items-center overflow-clip p-[8px] relative rounded-[8px] shrink-0 w-full transition-colors ${instructorName === instructor ? 'bg-[#e3effc]' : 'bg-white hover:bg-[#f7f7f7]'}`}
|
||||||
|
>
|
||||||
|
<div className="basis-0 flex flex-col font-normal grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[14px] text-[#515151]">
|
||||||
|
<p className="leading-[1.6]">{instructor}</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 교육 과정 이미지 */}
|
||||||
|
<div className="content-stretch flex flex-col gap-[20px] items-start relative shrink-0 w-full">
|
||||||
|
<div className="content-stretch flex gap-[20px] items-center relative shrink-0 w-full">
|
||||||
|
<div className="basis-0 content-stretch flex gap-[16px] grow items-center min-h-px min-w-px relative shrink-0">
|
||||||
|
<div className="content-stretch flex gap-[10px] items-center relative shrink-0 w-[177px]">
|
||||||
|
<p className="font-medium leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||||
|
교육 과정 이미지
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="content-stretch flex gap-[16px] items-center relative shrink-0">
|
||||||
|
<button className="bg-[#2b82e8] box-border content-stretch flex gap-2 h-[36px] items-center justify-center overflow-clip px-5 py-[13px] relative rounded-[8px] shrink-0 w-[114px] cursor-pointer hover:bg-[#1f6fc4] transition-colors">
|
||||||
|
<p className="font-medium leading-[1.6] not-italic relative shrink-0 text-[14px] text-white text-center text-nowrap whitespace-pre">
|
||||||
|
첨부
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="bg-[#f7f7f7] border border-[#eeeeee] border-solid box-border content-stretch flex flex-col gap-4 items-center px-[10px] py-[20px] relative rounded-[10px] shrink-0 w-full">
|
||||||
|
<div className="content-stretch flex flex-col gap-[2px] items-center relative shrink-0">
|
||||||
|
<div className="font-medium leading-[1.6] not-italic relative shrink-0 text-[#b9b9b9] text-[16px] text-center text-nowrap whitespace-pre">
|
||||||
|
<p className="mb-0">30MB 미만의 교육 과정 이미지를 첨부해 주세요.</p>
|
||||||
|
<p>첨부하지 않을 경우 기본 이미지가 노출돼요.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
0
app/admin_lecture2/page.tsx
Normal file
0
app/admin_lecture2/page.tsx
Normal file
@@ -71,7 +71,7 @@ export default function LoginPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 아이디와 비밀번호 검증
|
// 아이디와 비밀번호 검증
|
||||||
if (username === 'admin' && password === '1234') {
|
if (username === 'qwre@naver.com' && password === '1234') {
|
||||||
// 로그인 성공
|
// 로그인 성공
|
||||||
localStorage.setItem('isLoggedIn', 'true');
|
localStorage.setItem('isLoggedIn', 'true');
|
||||||
// 아이디 기억하기 체크 시 아이디 저장
|
// 아이디 기억하기 체크 시 아이디 저장
|
||||||
|
|||||||
@@ -34,11 +34,14 @@ export default function MyLecturePage() {
|
|||||||
<header className="absolute content-stretch flex items-center justify-between left-[calc(12.5%+91px)] top-[43px] w-[1332px]">
|
<header className="absolute content-stretch flex items-center justify-between left-[calc(12.5%+91px)] top-[43px] w-[1332px]">
|
||||||
<div className="content-stretch flex gap-[99px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[99px] items-center relative shrink-0">
|
||||||
{/* 로고 */}
|
{/* 로고 */}
|
||||||
<div className="h-[74px] relative shrink-0 w-[72px]">
|
<button
|
||||||
|
onClick={() => router.push('/')}
|
||||||
|
className="h-[74px] relative shrink-0 w-[72px] cursor-pointer"
|
||||||
|
>
|
||||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||||
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
|
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</button>
|
||||||
{/* 메뉴 */}
|
{/* 메뉴 */}
|
||||||
<div className="content-stretch flex gap-[24px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[24px] items-center relative shrink-0">
|
||||||
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
|
||||||
|
|||||||
@@ -94,11 +94,14 @@ export default function MyLecturePage() {
|
|||||||
<header className="absolute content-stretch flex items-center justify-between left-[calc(12.5%+91px)] top-[43px] w-[1332px]">
|
<header className="absolute content-stretch flex items-center justify-between left-[calc(12.5%+91px)] top-[43px] w-[1332px]">
|
||||||
<div className="content-stretch flex gap-[99px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[99px] items-center relative shrink-0">
|
||||||
{/* 로고 */}
|
{/* 로고 */}
|
||||||
<div className="h-[74px] relative shrink-0 w-[72px]">
|
<button
|
||||||
|
onClick={() => router.push('/')}
|
||||||
|
className="h-[74px] relative shrink-0 w-[72px] cursor-pointer"
|
||||||
|
>
|
||||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||||
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
|
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</button>
|
||||||
{/* 메뉴 */}
|
{/* 메뉴 */}
|
||||||
<div className="content-stretch flex gap-[24px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[24px] items-center relative shrink-0">
|
||||||
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
|
||||||
@@ -320,7 +323,7 @@ export default function MyLecturePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 푸터 */}
|
{/* 푸터 */}
|
||||||
<footer className="absolute bg-[#f7f7f7] box-border content-stretch flex flex-col gap-[10px] h-[225px] items-start left-0 px-[243px] py-[39px] top-[1226px] w-full">
|
<footer className="absolute bg-[#f7f7f7] box-border content-stretch flex flex-col mt-[111px] gap-[10px] h-[225px] items-start left-0 px-[243px] py-[39px] top-[1226px] w-full">
|
||||||
<div className="content-stretch flex gap-[49px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[49px] items-center relative shrink-0">
|
||||||
{/* 로고 */}
|
{/* 로고 */}
|
||||||
<div className="h-[74px] relative shrink-0 w-[72px]">
|
<div className="h-[74px] relative shrink-0 w-[72px]">
|
||||||
|
|||||||
@@ -72,11 +72,14 @@ export default function HomePage() {
|
|||||||
<header className="absolute content-stretch flex items-center justify-between left-[calc(12.5%+91.375px)] top-[43px] w-[1332px]">
|
<header className="absolute content-stretch flex items-center justify-between left-[calc(12.5%+91.375px)] top-[43px] w-[1332px]">
|
||||||
<div className="content-stretch flex gap-[99px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[99px] items-center relative shrink-0">
|
||||||
{/* 로고 */}
|
{/* 로고 */}
|
||||||
<div className="h-[74px] relative shrink-0 w-[72px]">
|
<button
|
||||||
|
onClick={() => router.push('/')}
|
||||||
|
className="h-[74px] relative shrink-0 w-[72px] cursor-pointer"
|
||||||
|
>
|
||||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||||
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
|
<img alt="" className="absolute h-[291.74%] left-[-100%] max-w-none top-[-95.73%] w-[301.18%]" src={imgImage2} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</button>
|
||||||
{/* 메뉴 */}
|
{/* 메뉴 */}
|
||||||
<div className="content-stretch flex gap-[24px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[24px] items-center relative shrink-0">
|
||||||
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
|
<div className="content-stretch flex gap-[150px] items-center relative shrink-0">
|
||||||
|
|||||||
253
app/pwfind/page.tsx
Normal file
253
app/pwfind/page.tsx
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
export default function PasswordFindPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const [email, setEmail] = useState('');
|
||||||
|
const [newPassword, setNewPassword] = useState('');
|
||||||
|
const [confirmPassword, setConfirmPassword] = useState('');
|
||||||
|
const [emailError, setEmailError] = useState('');
|
||||||
|
const [newPasswordError, setNewPasswordError] = useState('');
|
||||||
|
const [confirmPasswordError, setConfirmPasswordError] = useState('');
|
||||||
|
const [isCodeSent, setIsCodeSent] = useState(false);
|
||||||
|
|
||||||
|
const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setEmail(value);
|
||||||
|
if (emailError) {
|
||||||
|
setEmailError('');
|
||||||
|
}
|
||||||
|
// 이메일이 변경되면 인증 상태 초기화
|
||||||
|
if (isCodeSent) {
|
||||||
|
setIsCodeSent(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNewPasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setNewPassword(value);
|
||||||
|
if (newPasswordError) {
|
||||||
|
setNewPasswordError('');
|
||||||
|
}
|
||||||
|
// 새 비밀번호가 변경되면 확인 비밀번호도 다시 검증
|
||||||
|
if (confirmPassword && value !== confirmPassword) {
|
||||||
|
setConfirmPasswordError('비밀번호와 일치하지 않아요.');
|
||||||
|
} else if (confirmPassword && value === confirmPassword) {
|
||||||
|
setConfirmPasswordError('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfirmPasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setConfirmPassword(value);
|
||||||
|
if (confirmPasswordError) {
|
||||||
|
setConfirmPasswordError('');
|
||||||
|
}
|
||||||
|
// 비밀번호 확인 실시간 검증
|
||||||
|
if (value && newPassword && value !== newPassword) {
|
||||||
|
setConfirmPasswordError('비밀번호와 일치하지 않아요.');
|
||||||
|
} else if (value && newPassword && value === newPassword) {
|
||||||
|
setConfirmPasswordError('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateEmail = (email: string) => {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return emailRegex.test(email);
|
||||||
|
};
|
||||||
|
|
||||||
|
const validatePassword = (password: string) => {
|
||||||
|
return password.length >= 8 && password.length <= 16 && /[a-zA-Z]/.test(password) && /[0-9]/.test(password);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSendCode = () => {
|
||||||
|
if (!email.trim()) {
|
||||||
|
setEmailError('이메일을 입력해 주세요.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!validateEmail(email)) {
|
||||||
|
setEmailError('올바른 이메일을 입력해주세요.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: 인증번호 발송 API 호출
|
||||||
|
setIsCodeSent(true);
|
||||||
|
setEmailError('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setEmailError('');
|
||||||
|
setNewPasswordError('');
|
||||||
|
setConfirmPasswordError('');
|
||||||
|
|
||||||
|
let isValid = true;
|
||||||
|
|
||||||
|
if (!email.trim()) {
|
||||||
|
setEmailError('이메일을 입력해 주세요.');
|
||||||
|
isValid = false;
|
||||||
|
} else if (!validateEmail(email)) {
|
||||||
|
setEmailError('올바른 이메일을 입력해주세요.');
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCodeSent) {
|
||||||
|
setEmailError('인증번호를 발송해주세요.');
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newPassword.trim()) {
|
||||||
|
setNewPasswordError('새 비밀번호를 입력해 주세요.');
|
||||||
|
isValid = false;
|
||||||
|
} else if (!validatePassword(newPassword)) {
|
||||||
|
setNewPasswordError('비밀번호는 8~16자의 영문/숫자를 포함해야 합니다.');
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!confirmPassword.trim()) {
|
||||||
|
setConfirmPasswordError('새 비밀번호 확인을 입력해 주세요.');
|
||||||
|
isValid = false;
|
||||||
|
} else if (newPassword !== confirmPassword) {
|
||||||
|
setConfirmPasswordError('비밀번호와 일치하지 않아요.');
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
// TODO: 비밀번호 재설정 API 호출
|
||||||
|
router.push('/login');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const canSubmit = email.trim() !== '' &&
|
||||||
|
newPassword.trim() !== '' &&
|
||||||
|
confirmPassword.trim() !== '' &&
|
||||||
|
isCodeSent &&
|
||||||
|
newPassword === confirmPassword &&
|
||||||
|
validatePassword(newPassword);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative flex flex-col min-h-screen bg-white">
|
||||||
|
{/* 메인 콘텐츠 영역 - 카피라이트와 브라우저 최상단 사이의 중앙 */}
|
||||||
|
<div className="flex-1 flex flex-col items-center justify-center pb-[100px]">
|
||||||
|
{/* 제목 */}
|
||||||
|
<h1 className="font-bold text-[#1D1D1D] text-[32px] leading-tight">
|
||||||
|
비밀번호 재설정
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{/* 안내 문구 */}
|
||||||
|
<p className="text-[#515151] text-[18px] font-medium leading-normal mt-[40px]">
|
||||||
|
비밀번호 재설정을 위해 아래 정보를 입력해 주세요.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* 입력 폼 */}
|
||||||
|
<form
|
||||||
|
className="w-[829px] border border-[#b9b9b9] rounded-[8px] mt-[40px] px-[31px] py-[29px]"
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col gap-[20px]">
|
||||||
|
{/* 이메일(아이디) + 인증번호 발송 */}
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex gap-[10px] items-center justify-between h-[42px]">
|
||||||
|
<span className="text-[#515151] text-[18px] font-medium w-[177px]">
|
||||||
|
이메일(아이디)
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
value={email}
|
||||||
|
onChange={handleEmailChange}
|
||||||
|
className={`h-[42px] px-[10px] text-[18px] font-medium rounded-[8px] border placeholder:text-[#b9b9b9] bg-white w-[401px] focus:border-[#1669CA] focus:outline-none ${emailError ? 'border-[#E85D5D] text-[#E85D5D]' : 'border-[#b9b9b9] text-[#515151]'}`}
|
||||||
|
placeholder="이메일을 입력해 주세요."
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleSendCode}
|
||||||
|
className="bg-[#2B82E8] rounded-[10px] px-[10px] text-[18px] font-medium text-white h-[43px] w-[158px] transition hover:bg-[#1669ca] flex items-center justify-center"
|
||||||
|
>
|
||||||
|
인증번호 발송
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{emailError && (
|
||||||
|
<p className="text-[13px] text-[#E85D5D] ml-[187px] mt-[16px]">{emailError}</p>
|
||||||
|
)}
|
||||||
|
{isCodeSent && !emailError && (
|
||||||
|
<p className="text-[#1669ca] text-[12px] font-medium ml-[187px] mt-[16px]">
|
||||||
|
인증번호가 발송되었습니다. 이메일을 확인해 주세요.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 새 비밀번호 */}
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex gap-[16px] items-center h-[42px]">
|
||||||
|
<span className="text-[#515151] text-[18px] font-medium w-[177px]">
|
||||||
|
새 비밀번호
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
value={newPassword}
|
||||||
|
onChange={handleNewPasswordChange}
|
||||||
|
className={`flex-1 h-[42px] px-[10px] text-[18px] font-medium rounded-[8px] border placeholder:text-[#b9b9b9] bg-white focus:border-[#1669CA] focus:outline-none ${newPasswordError ? 'border-[#E85D5D] text-[#E85D5D]' : 'border-[#b9b9b9] text-[#515151]'}`}
|
||||||
|
placeholder="새 비밀번호를 입력해 주세요."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{newPasswordError && (
|
||||||
|
<p className="text-[13px] text-[#E85D5D] ml-[193px] mt-[16px]">{newPasswordError}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 새 비밀번호 확인 */}
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex gap-[16px] items-center h-[42px]">
|
||||||
|
<span className="text-[#515151] text-[18px] font-medium w-[177px]">
|
||||||
|
새 비밀번호 확인
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
value={confirmPassword}
|
||||||
|
onChange={handleConfirmPasswordChange}
|
||||||
|
className={`flex-1 h-[42px] px-[10px] text-[18px] font-medium rounded-[8px] border placeholder:text-[#b9b9b9] bg-white focus:border-[#1669CA] focus:outline-none ${confirmPasswordError ? 'border-[#E85D5D] text-[#E85D5D]' : 'border-[#b9b9b9] text-[#515151]'}`}
|
||||||
|
placeholder="새 비밀번호를 다시 입력해 주세요."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{confirmPasswordError && (
|
||||||
|
<p className="text-[13px] text-[#E85D5D] ml-[193px] mt-[16px]">{confirmPasswordError}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{/* 버튼 영역 */}
|
||||||
|
<div className="mt-[54px] flex gap-[21px]">
|
||||||
|
<Link
|
||||||
|
href="/login"
|
||||||
|
className="border border-[#1669ca] bg-white rounded-[10px] h-[55px] w-[334px] flex items-center justify-center font-medium text-[#515151] text-[18px] hover:bg-[#EDF4FC] transition"
|
||||||
|
>
|
||||||
|
돌아가기
|
||||||
|
</Link>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleSubmit}
|
||||||
|
disabled={!canSubmit}
|
||||||
|
className={`rounded-[10px] h-[55px] w-[334px] font-medium text-[18px] transition flex items-center justify-center
|
||||||
|
${canSubmit
|
||||||
|
? 'bg-[#2B82E8] text-white hover:bg-[#1669ca]'
|
||||||
|
: 'bg-[#b9b9b9] text-white cursor-not-allowed'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
비밀번호 재설정
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 카피라이트 */}
|
||||||
|
<footer className="absolute bottom-[51.5px] left-1/2 -translate-x-1/2 flex flex-col items-center">
|
||||||
|
<p className="text-[16px] text-[rgba(0,0,0,0.55)] leading-[1.45] font-medium tracking-[-0.08px]">
|
||||||
|
Copyright ⓒ 2025 XL LMS. All rights reserved
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
448
package-lock.json
generated
448
package-lock.json
generated
@@ -8,6 +8,8 @@
|
|||||||
"name": "xr_lms",
|
"name": "xr_lms",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/better-sqlite3": "^7.6.13",
|
||||||
|
"better-sqlite3": "^12.4.1",
|
||||||
"next": "16.0.1",
|
"next": "16.0.1",
|
||||||
"react": "19.2.0",
|
"react": "19.2.0",
|
||||||
"react-dom": "19.2.0"
|
"react-dom": "19.2.0"
|
||||||
@@ -1486,6 +1488,15 @@
|
|||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/better-sqlite3": {
|
||||||
|
"version": "7.6.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz",
|
||||||
|
"integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||||
@@ -1511,7 +1522,6 @@
|
|||||||
"version": "20.19.24",
|
"version": "20.19.24",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.24.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.24.tgz",
|
||||||
"integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==",
|
"integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
@@ -2400,6 +2410,26 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/baseline-browser-mapping": {
|
"node_modules/baseline-browser-mapping": {
|
||||||
"version": "2.8.20",
|
"version": "2.8.20",
|
||||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.20.tgz",
|
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.20.tgz",
|
||||||
@@ -2410,6 +2440,40 @@
|
|||||||
"baseline-browser-mapping": "dist/cli.js"
|
"baseline-browser-mapping": "dist/cli.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/better-sqlite3": {
|
||||||
|
"version": "12.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.4.1.tgz",
|
||||||
|
"integrity": "sha512-3yVdyZhklTiNrtg+4WqHpJpFDd+WHTg2oM7UcR80GqL05AOV0xEJzc6qNvFYoEtE+hRp1n9MpN6/+4yhlGkDXQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bindings": "^1.5.0",
|
||||||
|
"prebuild-install": "^7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20.x || 22.x || 23.x || 24.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bindings": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"file-uri-to-path": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bl": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "^5.5.0",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"readable-stream": "^3.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.12",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
@@ -2468,6 +2532,30 @@
|
|||||||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/call-bind": {
|
"node_modules/call-bind": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||||
@@ -2565,6 +2653,12 @@
|
|||||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chownr": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/client-only": {
|
"node_modules/client-only": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||||
@@ -2706,6 +2800,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/decompress-response": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mimic-response": "^3.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/deep-extend": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/deep-is": {
|
"node_modules/deep-is": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||||
@@ -2753,7 +2871,6 @@
|
|||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||||
"devOptional": true,
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
@@ -2801,6 +2918,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/end-of-stream": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.18.3",
|
"version": "5.18.3",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
||||||
@@ -3439,6 +3565,15 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expand-template": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
||||||
|
"license": "(MIT OR WTFPL)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
@@ -3513,6 +3648,12 @@
|
|||||||
"node": ">=16.0.0"
|
"node": ">=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/file-uri-to-path": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/fill-range": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
@@ -3580,6 +3721,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fs-constants": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
@@ -3711,6 +3858,12 @@
|
|||||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/github-from-package": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||||
|
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/glob-parent": {
|
"node_modules/glob-parent": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||||
@@ -3892,6 +4045,26 @@
|
|||||||
"hermes-estree": "0.25.1"
|
"hermes-estree": "0.25.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||||
@@ -3929,6 +4102,18 @@
|
|||||||
"node": ">=0.8.19"
|
"node": ">=0.8.19"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/ini": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/internal-slot": {
|
"node_modules/internal-slot": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
||||||
@@ -4879,6 +5064,18 @@
|
|||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mimic-response": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
@@ -4896,12 +5093,17 @@
|
|||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mkdirp-classic": {
|
||||||
|
"version": "0.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||||
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@@ -4927,6 +5129,12 @@
|
|||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/napi-build-utils": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/napi-postinstall": {
|
"node_modules/napi-postinstall": {
|
||||||
"version": "0.3.4",
|
"version": "0.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
|
||||||
@@ -5030,6 +5238,30 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-abi": {
|
||||||
|
"version": "3.80.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.80.0.tgz",
|
||||||
|
"integrity": "sha512-LyPuZJcI9HVwzXK1GPxWNzrr+vr8Hp/3UqlmWxxh8p54U1ZbclOqbSog9lWHaCX+dBaiGi6n/hIX+mKu74GmPA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^7.3.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-abi/node_modules/semver": {
|
||||||
|
"version": "7.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||||
|
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-releases": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.26",
|
"version": "2.0.26",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz",
|
||||||
@@ -5160,6 +5392,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/optionator": {
|
"node_modules/optionator": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||||
@@ -5326,6 +5567,32 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prebuild-install": {
|
||||||
|
"version": "7.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
||||||
|
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"detect-libc": "^2.0.0",
|
||||||
|
"expand-template": "^2.0.3",
|
||||||
|
"github-from-package": "0.0.0",
|
||||||
|
"minimist": "^1.2.3",
|
||||||
|
"mkdirp-classic": "^0.5.3",
|
||||||
|
"napi-build-utils": "^2.0.0",
|
||||||
|
"node-abi": "^3.3.0",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"rc": "^1.2.7",
|
||||||
|
"simple-get": "^4.0.0",
|
||||||
|
"tar-fs": "^2.0.0",
|
||||||
|
"tunnel-agent": "^0.6.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"prebuild-install": "bin.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||||
@@ -5348,6 +5615,16 @@
|
|||||||
"react-is": "^16.13.1"
|
"react-is": "^16.13.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pump": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"end-of-stream": "^1.1.0",
|
||||||
|
"once": "^1.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
@@ -5379,6 +5656,30 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/rc": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||||
|
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
||||||
|
"dependencies": {
|
||||||
|
"deep-extend": "^0.6.0",
|
||||||
|
"ini": "~1.3.0",
|
||||||
|
"minimist": "^1.2.0",
|
||||||
|
"strip-json-comments": "~2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"rc": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rc/node_modules/strip-json-comments": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "19.2.0",
|
"version": "19.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
|
||||||
@@ -5407,6 +5708,20 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/reflect.getprototypeof": {
|
"node_modules/reflect.getprototypeof": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
||||||
@@ -5547,6 +5862,26 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/safe-push-apply": {
|
"node_modules/safe-push-apply": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
|
||||||
@@ -5802,6 +6137,51 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/simple-concat": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/simple-get": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"decompress-response": "^6.0.0",
|
||||||
|
"once": "^1.3.1",
|
||||||
|
"simple-concat": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
@@ -5832,6 +6212,15 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string.prototype.includes": {
|
"node_modules/string.prototype.includes": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
|
||||||
@@ -6038,6 +6427,34 @@
|
|||||||
"url": "https://opencollective.com/webpack"
|
"url": "https://opencollective.com/webpack"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tar-fs": {
|
||||||
|
"version": "2.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
||||||
|
"integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chownr": "^1.1.1",
|
||||||
|
"mkdirp-classic": "^0.5.2",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"tar-stream": "^2.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tar-stream": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bl": "^4.0.3",
|
||||||
|
"end-of-stream": "^1.4.1",
|
||||||
|
"fs-constants": "^1.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.15",
|
"version": "0.2.15",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
@@ -6144,6 +6561,18 @@
|
|||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
|
"node_modules/tunnel-agent": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@@ -6296,7 +6725,6 @@
|
|||||||
"version": "6.21.0",
|
"version": "6.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/unrs-resolver": {
|
"node_modules/unrs-resolver": {
|
||||||
@@ -6375,6 +6803,12 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
@@ -6490,6 +6924,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/yallist": {
|
"node_modules/yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
"lint": "eslint"
|
"lint": "eslint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/better-sqlite3": "^7.6.13",
|
||||||
|
"better-sqlite3": "^12.4.1",
|
||||||
"next": "16.0.1",
|
"next": "16.0.1",
|
||||||
"react": "19.2.0",
|
"react": "19.2.0",
|
||||||
"react-dom": "19.2.0"
|
"react-dom": "19.2.0"
|
||||||
|
|||||||
15
public/svg/chevron_middle.tsx
Normal file
15
public/svg/chevron_middle.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
export default function ChevronMiddle() {
|
||||||
|
return (
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_40000054_6401)">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7083 15.7073C12.5208 15.8948 12.2665 16.0001 12.0013 16.0001C11.7362 16.0001 11.4818 15.8948 11.2943 15.7073L5.63732 10.0503C5.54181 9.9581 5.46563 9.84775 5.41322 9.72575C5.36081 9.60374 5.33322 9.47252 5.33207 9.33974C5.33092 9.20696 5.35622 9.07529 5.4065 8.95239C5.45678 8.82949 5.53103 8.71784 5.62492 8.62395C5.71882 8.53006 5.83047 8.4558 5.95337 8.40552C6.07626 8.35524 6.20794 8.32994 6.34072 8.33109C6.4735 8.33225 6.60472 8.35983 6.72672 8.41224C6.84873 8.46465 6.95907 8.54083 7.05132 8.63634L12.0013 13.5863L16.9513 8.63634C17.1399 8.45418 17.3925 8.35339 17.6547 8.35567C17.9169 8.35795 18.1677 8.46312 18.3531 8.64852C18.5385 8.83393 18.6437 9.08474 18.646 9.34694C18.6483 9.60914 18.5475 9.86174 18.3653 10.0503L12.7083 15.7073Z" fill="#515151" />
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_40000054_6401">
|
||||||
|
<rect width="24" height="24" fill="white" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
14
public/svg/close.tsx
Normal file
14
public/svg/close.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export default function Close() {
|
||||||
|
return (
|
||||||
|
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_40000054_6405)">
|
||||||
|
<path d="M20.3033 22.0714L15 16.7681L9.6967 22.0714L7.92893 20.3036L13.2322 15.0003L7.92893 9.69704L9.6967 7.92928L15 13.2326L20.3033 7.92928L22.0711 9.69704L16.7678 15.0003L22.0711 20.3036L20.3033 22.0714Z" fill="#515151" />
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_40000054_6405">
|
||||||
|
<rect width="30" height="30" fill="white" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user