+
{name}
);
diff --git a/FE/src/components/common/header/Header.tsx b/FE/src/components/common/header/Header.tsx
index 53c27539..0ec97a95 100644
--- a/FE/src/components/common/header/Header.tsx
+++ b/FE/src/components/common/header/Header.tsx
@@ -1,15 +1,36 @@
+"use client";
+import { useEffect, useState } from "react";
import CreateBtn from "./CreateBtn";
+import LoginRedirectBtn from "./LoginRedirectBtn";
import Logo from "./Logo";
import UserBtn from "./UserBtn";
+import { CheckIsLoggedIn } from "@/utils/authWithStorage";
const Header = () => {
+ const [isLoggedIn, setIsLoggedIn] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ const isLoggedIn = CheckIsLoggedIn();
+ setIsLoggedIn(isLoggedIn);
+ setIsLoading(false);
+ }, []);
+
return (
-
-
+
+ {!isLoading && (
+
+ {isLoggedIn ? (
+ <>
+
+
+ >
+ ) : (
+
+ )}
+
+ )}
);
};
diff --git a/FE/src/components/common/header/LoginRedirectBtn.tsx b/FE/src/components/common/header/LoginRedirectBtn.tsx
new file mode 100644
index 00000000..06ff0a15
--- /dev/null
+++ b/FE/src/components/common/header/LoginRedirectBtn.tsx
@@ -0,0 +1,20 @@
+import Image from "next/image";
+import Link from "../Link";
+import ROUTES from "@/constants/ROUTES";
+
+const LOGIN = "로그인 후 사용해주세요!";
+
+export default function LoginRedirectBtn() {
+ return (
+
+
+ {LOGIN}
+
+ );
+}
diff --git a/FE/src/components/common/header/Logo.tsx b/FE/src/components/common/header/Logo.tsx
index db45bdf3..f5b26fa2 100644
--- a/FE/src/components/common/header/Logo.tsx
+++ b/FE/src/components/common/header/Logo.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import Image from "next/image";
import { usePathname, useRouter } from "next/navigation";
import ROUTES from "@/constants/ROUTES";
@@ -8,16 +6,22 @@ const INIT_CATEGORY = "all";
const INIT_STATUS = "active";
const INIT_PAGE = "1";
-const Logo = () => {
+interface LogoProps {
+ isLoggedIn: boolean;
+}
+
+const Logo = ({ isLoggedIn }: LogoProps) => {
const router = useRouter();
const pathname = usePathname();
+ const mainUrl = isLoggedIn ? ROUTES.MAIN : ROUTES.GUEST_MAIN;
+
const handleClick = () => {
- if (pathname === ROUTES.MAIN) {
- window.location.href = `${ROUTES.MAIN}?category=${INIT_CATEGORY}&status=${INIT_STATUS}&page=${INIT_PAGE}`;
+ if (pathname === mainUrl) {
+ window.location.href = `${mainUrl}?category=${INIT_CATEGORY}&status=${INIT_STATUS}&page=${INIT_PAGE}`;
return;
}
- router.push(ROUTES.MAIN);
+ router.push(mainUrl);
};
return (
diff --git a/FE/src/components/common/header/UserBtn.tsx b/FE/src/components/common/header/UserBtn.tsx
index ada937e9..921fc870 100644
--- a/FE/src/components/common/header/UserBtn.tsx
+++ b/FE/src/components/common/header/UserBtn.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import Image from "next/image";
import UserActiveModal from "./Modal/UserActiveModal";
import useModal from "@/hooks/useModal";
diff --git a/FE/src/components/common/validate/Auth.tsx b/FE/src/components/common/validate/Auth.tsx
index 0f87d9d6..e226edec 100644
--- a/FE/src/components/common/validate/Auth.tsx
+++ b/FE/src/components/common/validate/Auth.tsx
@@ -5,16 +5,25 @@ import { useEffect } from "react";
import ROUTES from "@/constants/ROUTES";
import { deleteTokenInfo } from "@/utils/authWithStorage";
-const AuthValidate = () => {
+interface AuthValidateProps {
+ isHaveToLoggedInRoute?: boolean;
+}
+
+const AuthValidate = ({ isHaveToLoggedInRoute = true }: AuthValidateProps) => {
const router = useRouter();
useEffect(() => {
const accessToken = localStorage.getItem("accessToken");
const tokenExpiration = localStorage.getItem("tokenExpiration");
- if (!accessToken || !tokenExpiration) {
+ const isLoggedIn = accessToken || tokenExpiration;
+
+ if (isHaveToLoggedInRoute && !isLoggedIn) {
deleteTokenInfo();
router.push(ROUTES.LOGIN);
}
+ if (!isHaveToLoggedInRoute && isLoggedIn) {
+ router.push(ROUTES.MAIN);
+ }
}, []);
return <>>;
diff --git a/FE/src/components/login/RightSection.tsx b/FE/src/components/login/RightSection.tsx
index bcf030c1..72a2c867 100644
--- a/FE/src/components/login/RightSection.tsx
+++ b/FE/src/components/login/RightSection.tsx
@@ -1,5 +1,7 @@
import Title from "../common/Title";
-import SlackLoginSection from "./slack/LoginSection";
+import GuestLoginButton from "./guest/GuestLoginButton";
+import LoginSection from "./slack/LoginSection";
+import SlackLoginButton from "./slack/SlackLoginButton";
const LoginRightSection = () => {
return (
@@ -8,10 +10,17 @@ const LoginRightSection = () => {
className="flex flex-col items-center justify-center gap-24"
>
-
+
+ }
+ />
+ }
+ />
+
);
};
export default LoginRightSection;
-
-//
diff --git a/FE/src/components/login/guest/GuestLoginButton.tsx b/FE/src/components/login/guest/GuestLoginButton.tsx
new file mode 100644
index 00000000..6c556b66
--- /dev/null
+++ b/FE/src/components/login/guest/GuestLoginButton.tsx
@@ -0,0 +1,12 @@
+import StyledLoginButton from "../ui/StyledLoginButton";
+
+export default function GuestLoginButton() {
+ return (
+
-
에코노베이션 슬랙으로 로그인
-
+
+
{title}
+ {loginBtnComponent}
);
};
-export default SlackLoginSection;
+export default LoginSection;
diff --git a/FE/src/components/login/slack/LoginButton.tsx b/FE/src/components/login/slack/SlackLoginButton.tsx
similarity index 70%
rename from FE/src/components/login/slack/LoginButton.tsx
rename to FE/src/components/login/slack/SlackLoginButton.tsx
index b7a29e8a..b1f4ad75 100644
--- a/FE/src/components/login/slack/LoginButton.tsx
+++ b/FE/src/components/login/slack/SlackLoginButton.tsx
@@ -1,9 +1,8 @@
"use client";
-import Image from "next/image";
-import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useEffect } from "react";
+import StyledLoginButton from "../ui/StyledLoginButton";
import { useSlackLoginMutation } from "@/hooks/query/useAuthQuery";
const SlackLoginButton = () => {
@@ -24,13 +23,13 @@ const SlackLoginButton = () => {
}, [code]);
return (
-
-
-
슬랙으로 로그인
-
+
);
};
+
export default SlackLoginButton;
diff --git a/FE/src/components/login/ui/StyledLoginButton.tsx b/FE/src/components/login/ui/StyledLoginButton.tsx
new file mode 100644
index 00000000..21a5be66
--- /dev/null
+++ b/FE/src/components/login/ui/StyledLoginButton.tsx
@@ -0,0 +1,32 @@
+import classNames from "classnames";
+import Image from "next/image";
+import Link from "next/link";
+
+const defaultStyle = "flex w-64 justify-center gap-4 rounded-3xl py-3";
+
+const colors = {
+ slack: "bg-slack text-white text-paragraph",
+ guest: "bg-primary text-black text-paragraph",
+};
+
+interface StyledLoginButtonProps {
+ linkUrl: string;
+ buttonText: string;
+ imageUrl: string;
+ color: keyof typeof colors;
+}
+
+export default function StyledLoginButton({
+ linkUrl,
+ buttonText,
+ imageUrl,
+ color,
+}: StyledLoginButtonProps) {
+ const buttonStyle = classNames(defaultStyle, colors[color]);
+ return (
+
+
+
{buttonText}
+
+ );
+}
diff --git a/FE/src/components/main/ProgramList.tsx b/FE/src/components/main/ProgramList.tsx
index cabccb60..b661ff5c 100644
--- a/FE/src/components/main/ProgramList.tsx
+++ b/FE/src/components/main/ProgramList.tsx
@@ -10,6 +10,7 @@ interface ProgramListProps {
programStatus?: ProgramStatus;
page?: number;
setPage: (page: number) => void;
+ isLoggedIn: boolean;
}
const ProgramList = ({
@@ -17,6 +18,7 @@ const ProgramList = ({
programStatus = "active",
page = 1,
setPage: handleSetPage,
+ isLoggedIn,
}: ProgramListProps) => {
const queryClient = useQueryClient();
const { data: programListData } = useGetProgramList({
@@ -24,6 +26,7 @@ const ProgramList = ({
programStatus,
page: page - 1,
size: PROGRAM.LIST_SIZE,
+ isLoggedIn,
});
queryClient.setQueryData
(["totalPage"], programListData.totalPage);
@@ -33,7 +36,11 @@ const ProgramList = ({
<>
{programs.map((program) => (
-
+
))}
{
+const ProgramListItem = ({ programData, isLoggedIn }: ProgramListItemProps) => {
const { programId, title, deadLine } = programData;
+ const lingUrl = isLoggedIn
+ ? ROUTES.DETAIL(programId)
+ : ROUTES.GUEST_DETAIL(programId);
return (
diff --git a/FE/src/components/programDetail/attendee/AttendeeInfo.container.tsx b/FE/src/components/programDetail/attendee/AttendeeInfo.container.tsx
index 12c92ed5..4e24007f 100644
--- a/FE/src/components/programDetail/attendee/AttendeeInfo.container.tsx
+++ b/FE/src/components/programDetail/attendee/AttendeeInfo.container.tsx
@@ -2,22 +2,45 @@
import { ErrorBoundary } from "react-error-boundary";
import AttendeeInfo from "./AttendeeInfo";
+import BluredAttedee from "./BluredAttedee";
import ErrorFallback from "@/components/common/ErrorFallback";
interface AttendeeInfoContainerProps {
programId: number;
+ isLoggedIn: boolean;
}
-const AttendeeInfoContainer = ({ programId }: AttendeeInfoContainerProps) => {
+export const attendStatuses = [
+ "attend",
+ "late",
+ "absent",
+ "nonResponse",
+] as const;
+
+const AttendeeInfoContainer = ({
+ programId,
+ isLoggedIn,
+}: AttendeeInfoContainerProps) => {
return (
-
-
-
+ <>
+ {!isLoggedIn &&
+ attendStatuses.map((status) => (
+
+ ))}
+
+
+
+ {isLoggedIn &&
+ attendStatuses.map((status) => (
+
+ ))}
+
+
+ >
);
};
export default AttendeeInfoContainer;
diff --git a/FE/src/components/programDetail/attendee/BluredAttedee.tsx b/FE/src/components/programDetail/attendee/BluredAttedee.tsx
new file mode 100644
index 00000000..ee73847d
--- /dev/null
+++ b/FE/src/components/programDetail/attendee/BluredAttedee.tsx
@@ -0,0 +1,35 @@
+import AttendeeStatus from "./AttendeeStatus";
+import { MemberAttendStatusInfoDto } from "@/apis/dtos/member.dto";
+import MemberList from "@/components/common/MemberList";
+import { AttendStatus } from "@/types/member";
+
+const mockMember: MemberAttendStatusInfoDto = {
+ memberId: 1,
+ name: "20기 박건규",
+ attendStatus: "attend",
+};
+
+interface BluredAttedeeProps {
+ status: AttendStatus;
+}
+
+export default function BluredAttedee({ status }: BluredAttedeeProps) {
+ const population =
+ status === "attend"
+ ? 52
+ : status === "late"
+ ? 3
+ : status === "absent"
+ ? 1
+ : 0;
+ const members = Array.from({ length: population }, (_, i) => ({
+ ...mockMember,
+ memberId: i + 1,
+ }));
+ return (
+
+ );
+}
diff --git a/FE/src/components/programDetail/program/ProgramInfo.tsx b/FE/src/components/programDetail/program/ProgramInfo.tsx
index 632832ad..6c9a016c 100644
--- a/FE/src/components/programDetail/program/ProgramInfo.tsx
+++ b/FE/src/components/programDetail/program/ProgramInfo.tsx
@@ -7,14 +7,15 @@ import { useGetProgramById } from "@/hooks/query/useProgramQuery";
interface ProgramInfoProps {
programId: number;
+ isLoggedIn: boolean;
}
-const ProgramInfo = ({ programId }: ProgramInfoProps) => {
+const ProgramInfo = ({ programId, isLoggedIn }: ProgramInfoProps) => {
const {
data: programData,
isLoading,
isError,
- } = useGetProgramById(programId);
+ } = useGetProgramById(programId, isLoggedIn);
if (isLoading) return ;
if (isError) return 에러 발생
;
diff --git a/FE/src/components/programDetail/userAttendModal/LoginModal.tsx b/FE/src/components/programDetail/userAttendModal/LoginModal.tsx
new file mode 100644
index 00000000..d3f4a3bf
--- /dev/null
+++ b/FE/src/components/programDetail/userAttendModal/LoginModal.tsx
@@ -0,0 +1,24 @@
+// import AttendToggleLabel from "./AttendToggleLabel";
+import Link from "next/link";
+import AttendStatusToggle from "@/components/common/attendStatusToggle/AttendStatusToggle";
+import StatusToggleItem from "@/components/common/attendStatusToggle/StatusToggleItem";
+import ROUTES from "@/constants/ROUTES";
+
+export default function LoginModal() {
+ return (
+
+
+
+
+
로그인 후 사용해주세요!
+
{}}
+ />
+
+ );
+}
diff --git a/FE/src/components/programDetail/userAttendModal/UserAttendModal.container.tsx b/FE/src/components/programDetail/userAttendModal/UserAttendModal.container.tsx
index ee68ae12..653782ad 100644
--- a/FE/src/components/programDetail/userAttendModal/UserAttendModal.container.tsx
+++ b/FE/src/components/programDetail/userAttendModal/UserAttendModal.container.tsx
@@ -3,6 +3,7 @@
import classNames from "classnames";
import Image from "next/image";
import { ErrorBoundary } from "react-error-boundary";
+import LoginModal from "./LoginModal";
import UserAttendModal from "./UserAttendModal";
import ErrorFallbackNoIcon from "@/components/common/ErrorFallbackNoIcon";
import useModal from "@/hooks/useModal";
@@ -10,9 +11,13 @@ import useOutsideRef from "@/hooks/useOutsideRef";
interface UserAttendModalProps {
programId: number;
+ isLoggedIn: boolean;
}
-const UserAttendModalContainer = ({ programId }: UserAttendModalProps) => {
+const UserAttendModalContainer = ({
+ programId,
+ isLoggedIn,
+}: UserAttendModalProps) => {
const { isOpen, openModal, closeModal } = useModal();
const modalRef = useOutsideRef(closeModal);
@@ -26,7 +31,6 @@ const UserAttendModalContainer = ({ programId }: UserAttendModalProps) => {
const handleOpenModal = (e: React.MouseEvent) => {
e.stopPropagation();
- console.log("hi", isOpen);
isOpen ? closeModal() : openModal();
};
@@ -46,9 +50,13 @@ const UserAttendModalContainer = ({ programId }: UserAttendModalProps) => {
style={{ width: 38, height: 6 }}
/>
-