Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/designImage/notice/notice_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/designImage/notice/notice_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/MobileRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ import MobileArchivePage from './pages/mobile/MobileArchive';
import MobileArchiveDetailPage from './pages/mobile/MobileArchiveDetail';
import MobileMyBoard from './pages/mobileMyBoard/MyBoardPage';
import OAuthPage from './pages/login/OAuthPage';
import NoticePage from './mobile/pages/NoticePage';

export const mobileMainRoutes = [
{ path: '/', element: <OnboardingMobile /> },
{ path: '/login', element: <LoginPage setLogin={(isLogined) => isLogined === true} /> },
{ path: '/oauth-koreapas/:koreapasUUID?', element: <OAuthPage /> },
{ path: '/notice', element: <NoticePage /> },
];

export const mobileAuthRoutes = [
Expand Down
2 changes: 2 additions & 0 deletions src/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ import UserPage from './admin/pages/user';
import { IndexPage } from './admin/routes/sections';
import OnboardingPage from './pages/main/OnboardingPage';
import OAuthPage from './pages/login/OAuthPage';
import NoticePage from './pages/notice/noticePage';

const isLogined = true;

export const mainRoutes = [
{ path: '/', element: <OnboardingPage /> },
{ path: '/login', element: <LoginPage setLogin={(isLogined) => isLogined == true} /> },
{ path: '/oauth-koreapas/:koreapasUUID?', element: <OAuthPage /> },
{ path: '/notice', element: <NoticePage /> }, // 고객센터 페이지 추가
];

export const authRoutes = [
Expand Down
158 changes: 158 additions & 0 deletions src/assets/buttons/Button08_notice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import styled from 'styled-components';
import { useState } from 'react';
import Typography from '../Typography';
import React from 'react';

export interface FAQboxProps extends React.ComponentPropsWithRef<'div'> {
isOpen?: boolean;
onToggle?: () => void;
question?: string;
answer?: { text: string; bold: string }[][];
isPinned?: boolean; // 필독 여부 prop
}

const MainWrapper = styled.div<{ $isPinned?: boolean }>`
display: flex;
width: 52.449vw;
padding: 1.875vw 2.291vw;
flex-direction: column;
align-items: flex-start;
justify-content: center;
gap: 3.125vw;
flex-shrink: 0;
border-radius: 0.5208vw;
border: ${(props) =>
props.$isPinned ? '1px solid rgba(223, 223, 223, 0.40)' : '1px solid rgba(223, 223, 223, 0.4)'};
//background: ${(props) => (props.$isPinned ? 'rgba(228, 228, 228, 0.40)' : 'rgba(255, 255, 255, 0.6)')};
`;

const TitleWrapper = styled.div`
width: 52.449vw;
display: flex;
justify-content: space-between;
align-items: center;
`;

const ContentWrapper = styled.div`
width: 52.449vw;
display: flex;
flex-direction: column;
`;

// 필독 배지 스타일 컴포넌트 추가
const PinnedBox = styled.div`
display: flex;
width: 5.26vw;
height: 2.19vw;
//padding: 0.78vw 1.25vw;
justify-content: center;
align-items: center;
gap: 0.42vw;

border-radius: 52vw;
background: #d85888;
`;

const PinnedText = styled.div`
color: #fff;
text-align: center;
font-family: Pretendard;
font-size: 0.83vw;
font-style: normal;
font-weight: 700;
line-height: 150%;
`;

// 타이틀과 배지를 감싸는 컨테이너
const TitleContainer = styled.div`
display: flex;
align-items: center;
gap: 0.625vw;
`;

function Button08_notice(props: FAQboxProps) {
const {
isOpen = false,
onToggle,
question = '이중전공 지원 요건이 어떻게 되나요?',
answer = [
[{ text: '이중전공은 해당 학기에 아래 요건을 모두 만족하여야 지원 가능합니다.', bold: '500' }],
[{ text: '', bold: '' }],
[{ text: '가. 제 1전공이 배정된 자', bold: '700' }],
// ... 기존 answer 내용
],
isPinned = false, // 기본값은 false
...rest
} = props;

return (
<MainWrapper
$isPinned={isPinned}
style={{
background: isOpen ? 'rgba(255, 255, 255, 0.6)' : (isPinned ? 'rgba(228, 228, 228, 0.40)' : 'rgba(255, 255, 255, 0.6)'),
border: isOpen ? '1px solid #d85888' : '1px solid rgba(223, 223, 223, 0.4)',
boxShadow: isOpen ? '0px 0px 0.625vw 0px rgba(216, 88, 136, 0.10)' : '',
}}
{...rest}
>
<TitleWrapper onClick={onToggle} style={{ cursor: 'pointer' }}>
<TitleContainer>
{isPinned && (
<PinnedBox>
<svg xmlns="http://www.w3.org/2000/svg" width="0.78vw" height="0.78vw" viewBox="0 0 15 16" fill="none">
<path d="M2.5 14.25V9.875" stroke="white" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M2.5 9.875C2.5 9.875 3.125 9.25 5 9.25C6.875 9.25 8.125 10.5 10 10.5C11.875 10.5 12.5 9.875 12.5 9.875V2.375C12.5 2.375 11.875 3 10 3C8.125 3 6.875 1.75 5 1.75C3.125 1.75 2.5 2.375 2.5 2.375V9.875Z"
fill="white"
stroke="white"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
<PinnedText>필독</PinnedText>
</PinnedBox>
)}
<Typography size="1.041vw" bold="500" style={{ lineHeight: '120%' }}>
{question}
</Typography>
</TitleContainer>
<img
src="../../designImage/UAngleDown.svg"
onClick={onToggle}
style={{
cursor: 'pointer',
transform: isOpen == true ? 'rotate(180deg)' : 'none',
width: '1.771vw',
height: '1.771vw',
}}
/>
</TitleWrapper>
{isOpen == true && (
<ContentWrapper>
{answer.map((lineAnswers, lineIndex) => (
<div key={lineIndex}>
{lineAnswers.map((answer, segmentIndex) =>
answer.text !== '' ? (
<Typography
key={segmentIndex}
size="0.9375vw"
bold={answer.bold}
style={{
lineHeight: '1.458vw',
}}
>
{answer.text}
</Typography>
) : (
<div key={segmentIndex} style={{ height: '1.458vw' }} />
),
)}
</div>
))}
</ContentWrapper>
)}
</MainWrapper>
);
}

export default Button08_notice;
4 changes: 4 additions & 0 deletions src/mobile/assets/base/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ function MobileHeader({ logined, setLogin }: HeaderProps) {
'default',
'default',
'default',
'default',
]);

useEffect(() => {
Expand Down Expand Up @@ -232,6 +233,9 @@ function MobileHeader({ logined, setLogin }: HeaderProps) {
<HeaderButton state={buttonStates[2]} onClick={() => navigate('/myboard')}>
마이보드
</HeaderButton>
<HeaderButton state={buttonStates[3]} onClick={() => navigate('/notice')}>
고객센터
</HeaderButton>
</ButtonWrapper>
</MainWrapper>
);
Expand Down
151 changes: 151 additions & 0 deletions src/mobile/assets/buttons/Button08_notice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import styled from 'styled-components';
import { useState } from 'react';
import Typography from '../../../assets/Typography';

export interface Button08Props extends React.ComponentPropsWithoutRef<'button'> {
isOpen?: boolean;
onToggle?: () => void;
question?: string;
answer?: { text: string; bold: string }[][]; // 타입 정의 수정
isPinned?: boolean; // 필독 여부 prop
}

function Button08_notice(props: Button08Props) {
const {
isOpen = false,
onToggle,
question = '이중전공 지원 요건이 어떻게 되나요?',
answer = [
[{ text: '이중전공은 해당 학기에 아래 요건을 모두 만족하여야 지원 가능합니다.', bold: '500' }],
[{ text: '', bold: '' }],
[{ text: '가. 제 1전공이 배정된 자', bold: '700' }],
// ... 기존 answer 내용
],
isPinned = false, // 기본값은 false
...rest
} = props;

const [showAnswer, setShowAnswer] = useState(isOpen);

const handleButtonClick = () => {
setShowAnswer(!showAnswer);
if (onToggle) {
onToggle();
}
};

return (
<MainWrapper showAnswer={showAnswer} $isPinned={isPinned}>
<QuestionBox>
<QuestionTextWrapper>
{isPinned && (
<PinnedBox>
<PinnedText>필독</PinnedText>
</PinnedBox>
)}
<Typography
size="3.89vw"
bold={showAnswer === false ? '500' : '700'}
style={{ lineHeight: '120%', textAlign: 'initial' }}
>
{question}
</Typography>
</QuestionTextWrapper>
<ImageWrapper showAnswer={showAnswer} onClick={handleButtonClick} src="../../../designImage/UAngleDown.svg" />
</QuestionBox>
{showAnswer === true && (
<AnswerBox>
{answer.map((paragraph, paragraphIndex) => (
<div key={paragraphIndex}>
{paragraph.map((sentence, sentenceIndex) => (
<div key={sentenceIndex}>
<Typography size="3.89vw" bold={sentence.bold} style={{ lineHeight: '150%' }}>
{sentence.text}
</Typography>
</div>
))}
{paragraphIndex !== answer.length - 1 && <ParagraphSpacing />}
</div>
))}
</AnswerBox>
)}
</MainWrapper>
);
}

const MainWrapper = styled.div<{ showAnswer: boolean; $isPinned?: boolean }>`
width: 91.11vw;
height: auto;
box-sizing: border-box;
padding: ${(props) => (props.showAnswer === true ? '6.67vw 5vw 6.67vw 3.06vw' : '4.44vw 5vw 4.17vw 3.06vw')};
border: ${(props) => (props.showAnswer === true ? '0.28vw solid #D85888' : '0.28vw solid #DFDFDF')};
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 13.89vw;
background: ${(props) =>
props.showAnswer === true ? '#FFF' : props.$isPinned ? '#F4F4F4' : 'rgba(255,255,255,0.6)'};
border-radius: 1.39vw;
border: ${(props) =>
props.$isPinned ? '1px solid rgba(223, 223, 223, 0.40)' : '1px solid rgba(223, 223, 223, 0.4)'};
`;

const QuestionBox = styled.div`
width: 81.39vw;
height: auto;
display: flex;
justify-content: space-between;
align-items: center;
gap: 5.83vw;
`;

// 질문과 필독 배지를 함께 감싸는 컨테이너 추가
const QuestionTextWrapper = styled.div`
display: flex;
align-items: center;
gap: 2vw; // 필독 배지와 질문 사이의 간격
`;

const AnswerBox = styled.div`
width: 81.39vw;
height: auto;
display: flex;
flex-direction: column;
`;

const ImageWrapper = styled.img<{ showAnswer: boolean }>`
width: 5vw;
height: 5vw;
cursor: pointer;
transform: ${(props) => (props.showAnswer === true ? 'rotate(180deg)' : 'none')};
`;

const ParagraphSpacing = styled.div`
width: auto;
height: 6.22vw;
`;

// 필독 배지 스타일 컴포넌트
const PinnedBox = styled.div`
display: flex;
min-width: 8.85vw;
padding: 1.11vw 1.67vw;
justify-content: center;
align-items: center;
border-radius: 999px;
background: rgba(216, 88, 136, 0.1);
`;

const PinnedText = styled.div`
color: #d85888;
text-align: center;
/* mob_tiny_Medium */
font-family: Pretendard;
font-size: 3.06vw;
font-style: normal;
font-weight: 500;
line-height: 120%;
`;

export default Button08_notice;
Loading