Skip to content

Commit

Permalink
add : 방과후 창조실
Browse files Browse the repository at this point in the history
add : 방과후 창조실
  • Loading branch information
phyuna0525 authored Apr 21, 2024
2 parents 397c46b + a58e775 commit 01617c7
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 45 deletions.
12 changes: 11 additions & 1 deletion src/api/afterManage/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { instance } from "..";
import { ChangeStatus, ClubList } from "../type";
import { ChangeStatus, ClubList, Type } from "../type";

export const GetClubList = (club: string) => {
return useQuery<ClubList[]>({
Expand All @@ -23,3 +23,13 @@ export const FixStatus = () => {
},
});
};

export const AllStudent = () => {
return useQuery<Type[]>({
queryKey: ["AllStudent"],
queryFn: async () => {
const response = await instance.get(`/after/search`);
return response.data;
},
});
};
7 changes: 7 additions & 0 deletions src/api/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,10 @@ export interface CountOutListType {
request: number;
classMove: number;
}

export interface Type {
grade: number;
class_num: number;
num: number;
name: string;
}
45 changes: 39 additions & 6 deletions src/app/afterManage/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import BackGround from "@/components/background";
import Button from "@/components/button";
import Dropdown from "@/components/dropdown";
import AfterList from "@/components/list/afterManage";
import Modal from "@/components/modal";
import { getStudentString } from "@/util/util";
import { useEffect, useState } from "react";

Expand All @@ -13,6 +14,7 @@ const AfterManage = () => {
const [selectedTab, setSelectedTab] = useState<boolean>(true);
const [selectClassTime, setSelectClassTime] = useState<number>(8);
const [selectClub, setSelectClub] = useState<string>("대동여지도");
const [modal, setMadal] = useState<boolean>(false);
const { data: getClub } = GetClubList(selectClub);
const { mutate: changeStatus } = FixStatus();

Expand Down Expand Up @@ -56,22 +58,41 @@ const AfterManage = () => {
setSelectedTab(tab);
};

const onAdd = () => {
setMadal(true);
};

return (
<BackGround
title="방과후 관리"
TabOK={true}
leftTab="전공 동아리"
rightTab="방과후(창조실)"
Dropdown={
<div className="flex gap-2">
<Dropdown type="club" onChange={handleClubChange} />
<Dropdown type="classTime" onChange={handleClassTimeChange} />
</div>
<>
{selectedTab ? (
<div className="flex gap-2">
<Dropdown type="club" onChange={handleClubChange} />
<Dropdown type="classTime" onChange={handleClassTimeChange} />
</div>
) : (
<div className="flex justify-between gap-2">
<Dropdown type="club" onChange={handleClubChange} />
<Button
colorType="tertiary"
buttonSize="extraSmall"
onClick={onAdd}
>
인원 추가
</Button>
</div>
)}
</>
}
TabOnclick={onClickTab}
>
<div className="overflow-y-scroll h-96 flex flex-col gap-4">
{selectedTab &&
{selectedTab ? (
clubList.map((item, index) => (
<AfterList
key={index}
Expand All @@ -82,7 +103,19 @@ const AfterManage = () => {
state2={item.status7}
state3={item.status8}
/>
))}
))
) : (
<div></div>
)}
{modal && (
<Modal
type="add"
heading1=""
buttonMessage="추가"
onCancel={() => {}}
onConfirm={() => {}}
/>
)}
</div>
<div className="absolute bottom-4% w-5/6 left-50%">
<Button
Expand Down
7 changes: 4 additions & 3 deletions src/app/main/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import CheckPage from "./checkPage";
import { GetName, GetTodaydirector } from "@/api/main";
import { getToday, getWeekDay } from "@/util/date";
import AfterManageImg from "@/assets/svg/aferManege.svg";
import attendanceImg from "@/assets/svg/attendance.svg"
import outingImg from "@/assets/svg/outing.svg"
import moveClassImg from "@/assets/svg/moveClass.svg"
import attendanceImg from "@/assets/svg/attendance.svg";
import outingImg from "@/assets/svg/outing.svg";
import moveClassImg from "@/assets/svg/moveClass.svg";

const Main = () => {
const [floor, setFloor] = useState<string>();
const { data: getDirector } = GetTodaydirector();
GetName();

useEffect(() => {
if (getDirector) setFloor(getDirector);
Expand Down
3 changes: 3 additions & 0 deletions src/assets/svg/cancel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 19 additions & 17 deletions src/components/background/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,28 @@ const BackGround: React.FC<Prop> = ({
TabOnclick,
}) => {
return (
<div className="min-w-fit min-h-full h-dvh px-6 py-3 bg-primary-1200">
<>
<Header />
<div className="py-3 gap-5 flex flex-col">
<div className="flex items-center gap-3 font-sans">
<div className="text-sub-title1-M">{title}</div>
<div className="text-sun-title3-M text-neutral-300">{subTitle}</div>
</div>
{Dropdown && <div>{Dropdown}</div>}
<div className="flex flex-col gap-6">
{TabOK && (
<Tab
firstText={leftTab || "Left Tab"}
SecondText={rightTab || "Right Tab"}
onClick={TabOnclick}
/>
)}
{children}
<div className="min-w-fit min-h-full h-dvh px-6 py-3 bg-primary-1200">
<div className="py-3 gap-5 flex flex-col">
<div className="flex items-center gap-3 font-sans">
<div className="text-sub-title1-M">{title}</div>
<div className="text-sun-title3-M text-neutral-300">{subTitle}</div>
</div>
{Dropdown && <div>{Dropdown}</div>}
<div className="flex flex-col gap-6">
{TabOK && (
<Tab
firstText={leftTab || "Left Tab"}
SecondText={rightTab || "Right Tab"}
onClick={TabOnclick}
/>
)}
{children}
</div>
</div>
</div>
</div>
</>
);
};

Expand Down
150 changes: 150 additions & 0 deletions src/components/input/auto.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import SelectedBadges from "./bedge/index";
import { AllStudent } from "@/api/afterManage";
import { setStudentNum } from "@/util/util";
import { Type } from "@/api/type";

interface ChangeProps {
text: string;
name: string;
}

interface InputProps {
placeholder?: string;
width?: string;
name?: string;
onChange: ({ text, name }: ChangeProps) => void;
value: string;
}

interface AutoInputProps extends InputProps {
selectedValues?: string[];
onRemoveBadge?: (value: string) => void;
}

export const PostSelectedValues: React.FC<AutoInputProps> = ({
selectedValues,
}) => {
return selectedValues;
};

const AutoInput: React.FC<AutoInputProps> = ({
placeholder,
width,
onChange,
value,
name = "",
}) => {
const [isAutoCompleteVisible, setIsAutoCompleteVisible] =
useState<boolean>(false);
const [filteredData, setFilteredData] = useState<string[]>([]);
const [selectedValues, setSelectedValues] = useState<string[]>([]);
const { data: GetStudentMutate } = AllStudent();

const containerClassName = `font-sans w-${width} h-auto border border-neutral-900 rounded flex justify-between items-center px-2 bg-neutral-900 hover:border-neutral-500 hover:bg-white active:border-secondary-500 caret-primary-500 focus:border-secondary-500`;

const [data, setData] = useState<Type[]>([]);

useEffect(() => {
localStorage.setItem("students", JSON.stringify(selectedValues));
}, [selectedValues]);

useEffect(() => {
if (GetStudentMutate) {
setData(GetStudentMutate);
}
}, [GetStudentMutate]);

useEffect(() => {
const students = data?.map((item) => `${setStudentNum(item)} ${item.name}`);
setStudent(students);
}, [data]);

const [student, setStudent] = useState<string[]>([]);

const inputClassName =
"h-10 px-2 border-none bg-transparent placeholder-neutral-500 focus:outline-none rounded font-sans w-full";

const handleInputChange = (inputText: string) => {
const filtered = student?.filter((item) =>
item.toLowerCase().includes(inputText.toLowerCase())
);
setFilteredData(filtered?.map((item) => item) || []);
setIsAutoCompleteVisible(true);

onChange({ text: inputText, name });
};

const dropdownRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setIsAutoCompleteVisible(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);

const handleSelectOption = (selectedOption: string) => {
onChange({ text: selectedOption, name });
setIsAutoCompleteVisible(false);

setSelectedValues((prevValues) => [...prevValues, selectedOption]);
};

const handleRemoveBadge = (value: string) => {
setSelectedValues((prevValues) => prevValues.filter((v) => v !== value));
};

const renderAutoComplete = () => (
<div className="absolute top-full left-0 bg-white border rounded-lg w-full text-Button-S z-20 h-auto max-h-64 overflow-y-scroll">
{filteredData.map((option) => (
<div
key={option}
onClick={() => {
handleSelectOption(option);
handleInputChange("");
setIsAutoCompleteVisible(false);
}}
className="flex py-2 px-3 hover:bg-primary-200 hover:text-white cursor-pointer"
>
{option}
</div>
))}
</div>
);

return (
<div className="flex flex-col gap-3" ref={dropdownRef}>
<div className="flex flex-col items-start relative">
<div className={containerClassName}>
<input
className={inputClassName}
type="text"
placeholder={placeholder}
width="full"
value={value}
onChange={(e) => handleInputChange(e.target.value)}
/>
</div>
{isAutoCompleteVisible && renderAutoComplete()}
</div>
<div className="flex gap-3 h-20 overflow-y-scroll">
<SelectedBadges
selectedValues={selectedValues}
onRemoveBadge={handleRemoveBadge}
/>
</div>
</div>
);
};

export default AutoInput;
40 changes: 40 additions & 0 deletions src/components/input/bedge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import Image from "next/image";
import React from "react";
import cancel from "@/assets/svg/cancel.svg";

interface BadgeProps {
value: string;
onRemove: () => void;
}

const Badge: React.FC<BadgeProps> = ({ value, onRemove }) => (
<div className=" w-max bg-neutral-900 text-neutral-50 rounded-lg px-3 justify-center py-2 flex items-center text-caption1 gap-2">
<span>{value}</span>
<Image
src={cancel}
alt=""
width={16}
height={16}
onClick={onRemove}
className="cursor-pointer"
/>
</div>
);

interface SelectedBadgesProps {
selectedValues: string[];
onRemoveBadge: (value: string) => void;
}

const SelectedBadges: React.FC<SelectedBadgesProps> = ({
selectedValues,
onRemoveBadge,
}) => (
<div className="flex gap-2 flex-wrap">
{selectedValues?.map((value) => (
<Badge key={value} value={value} onRemove={() => onRemoveBadge(value)} />
))}
</div>
);

export default SelectedBadges;
Loading

0 comments on commit 01617c7

Please sign in to comment.