Skip to content

Commit

Permalink
Feat/#40 마이페이지를 추가합니다. (#74)
Browse files Browse the repository at this point in the history
* fix: 디자인 시스템 색상을 수정합니다.

* feat: Toggle 컴포넌트를 추가합니다.

* feat: mypage 화면을 추가합니다.

* feat: 토글 배경 색상을 변경합니다.

* feat: 직군 선택 페이지를 추가합니다.

* fix: css prop에 $를 붙이도록 수정합니다.

* refactor: 불필요한 render 코드를 삭제합니다.
  • Loading branch information
sohyun215 authored Oct 7, 2024
1 parent 4ec0a5b commit 557f77b
Show file tree
Hide file tree
Showing 13 changed files with 621 additions and 28 deletions.
50 changes: 47 additions & 3 deletions app/(app)/my/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,56 @@
import { Stack } from 'expo-router';
import { Feather } from '@expo/vector-icons';
import { router, Stack } from 'expo-router';
import { Pressable } from 'react-native';

import { MY_NAVIGATIONS } from '@/constants';
import { color } from '@/styles/theme';
import { isMobile } from '@/utils';

function Layout() {
return (
<Stack>
<Stack
screenOptions={() => ({
title: '마이페이지',
headerStyle: { height: 40, backgroundColor: color.Background.Alternative },
headerTitleStyle: {
paddingTop: 8,
paddingBottom: 6,
fontFamily: 'Pretendard-SemiBold',
},
headerTitleAlign: 'center',
headerShadowVisible: false,
headerLeft: ({ canGoBack }) => (
<Pressable
onPress={() => (canGoBack ? router.back() : router.push(MY_NAVIGATIONS.HOME))}
style={{
paddingLeft: isMobile ? 0 : 20,
width: 24,
height: 24,
}}>
<Feather
name='chevron-left'
size={24}
/>
</Pressable>
),
})}>
<Stack.Screen
name='index'
options={{ title: '마이 페이지' }}
options={{ title: '마이페이지', headerLeft: () => null }}
/>
<Stack.Screen
name={MY_NAVIGATIONS.JOB}
options={{
title: '직군',
}}
/>
<Stack.Screen
name={MY_NAVIGATIONS.POLICY}
options={{
title: '서비스 정책',
}}
/>
<Stack.Screen name={MY_NAVIGATIONS.CANCEL_ACCOUNT} />
</Stack>
);
}
Expand Down
81 changes: 77 additions & 4 deletions app/(app)/my/cancel-account.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,86 @@
import { View } from 'react-native';
import styled from '@emotion/native';

import SolidButton from '@/components/common/button/SolidButton';
import Typography from '@/components/common/typography';
import { useTabBarEffect } from '@/hooks';
import { flexDirectionColumnCenter, flexDirectionRow } from '@/styles/common';
import { theme } from '@/styles/theme';

function CancelAccount() {
useTabBarEffect();

return (
<View>
<Typography>cancel-account</Typography>
</View>
<S.Container>
<Typography
variant='Heading1'
fontWeight='semiBold'>
정말 위프로를{'\n'}떠나실건가요?
</Typography>
<Typography style={{ marginTop: 16, marginBottom: 12 }}>
계정 탈퇴 신청 전 아래 사항을 확인 부탁드립니다.
</Typography>
<S.DescriptionContainer style={{ marginBottom: 6 }}>
<S.Number>1.</S.Number>
<S.DescriptionText fontWeight='semiBold'>
탈퇴 후 15일까지 재로그인을 통해 철회가 가능하며 이후에는 모든 회원 정보가 지체 없이
파기됩니다.
</S.DescriptionText>
</S.DescriptionContainer>
<S.DescriptionContainer>
<S.Number>2.</S.Number>
<S.DescriptionText>
휴대폰 인증을 통해 생성한 아이디가 여러 개인 경우 1개의 아이디를 탈퇴해도 다른 아이디는
계속해서 사용 가능합니다.
</S.DescriptionText>
</S.DescriptionContainer>

<S.ButtonSection>
<SolidButton
size='large'
full>
계속 이용하기
</SolidButton>
<Typography
style={{ textAlign: 'center' }}
variant='Body1/Normal'
color={theme.color.Label.Alternative}
breakWord>
탈퇴하기
</Typography>
</S.ButtonSection>
</S.Container>
);
}

export default CancelAccount;

const S = {
Container: styled.View`
flex: 1;
padding: 23px 20px 0;
color: ${({ theme }) => theme.color.Label.Normal};
background-color: ${({ theme }) => theme.color.Background.Alternative};
`,
Number: styled(Typography)`
flex-shrink: 0;
width: 20px;
height: 20px;
`,
DescriptionContainer: styled.View`
${flexDirectionRow};
align-items: flex-start;
`,
DescriptionText: styled(Typography)`
flex-shrink: 1;
flex-wrap: wrap;
`,
ButtonSection: styled.View`
${flexDirectionColumnCenter}
position: absolute;
right: 0;
bottom: 0;
left: 0;
gap: 8px;
padding: 12px 20px 30px;
`,
};
17 changes: 12 additions & 5 deletions app/(app)/my/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { View } from 'react-native';
import { SafeAreaView } from 'react-native';

import Typography from '@/components/common/typography';
import MenuList from '@/components/mypage/MenuList';
import Profile from '@/components/mypage/Profile';
import { color } from '@/styles/theme';

function My() {
return (
<View>
<Typography>:)</Typography>
</View>
<SafeAreaView style={{ flex: 1, backgroundColor: color.Background.Alternative }}>
<Profile
uri='https://avatars.githubusercontent.com/u/79398566?v=4'
name='김소현'
job='개발자'
/>
<MenuList />
</SafeAreaView>
);
}

Expand Down
130 changes: 130 additions & 0 deletions app/(app)/my/job.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import styled from '@emotion/native';
import { router } from 'expo-router';
import { useState } from 'react';
import { Platform } from 'react-native';

import SolidButton from '@/components/common/button/SolidButton';
import Typography from '@/components/common/typography';
import { useTabBarEffect } from '@/hooks';
import { flexDirectionColumnCenter } from '@/styles/common';
import { theme } from '@/styles/theme';

const JOB_LIST = ['개발자', '디자이너', 'PM', '그 외'];

function JOB() {
useTabBarEffect();

const [selectedJob, setSelectedJob] = useState<string | null>(null);
const [otherJob, setOtherJob] = useState<string>('');

const isSelected = (job: string) => selectedJob === job;

const handleSaveJob = () => {
// TODO: 직군 저장
console.log(selectedJob === '그 외' ? otherJob : selectedJob);
router.navigate('my');
};

return (
<S.Container>
<Typography
variant='Title2'
fontWeight='bold'>
무슨 일을 하시는지{'\n'}알려주세요
</Typography>
<S.JobList>
{JOB_LIST.map((job) =>
job === '그 외' && isSelected(job) ? (
<S.InputContainer key={job}>
<S.TextInput
placeholder='적어주세요'
placeholderTextColor={theme.color.Label.Neutral}
value={otherJob}
onChangeText={setOtherJob}
/>
</S.InputContainer>
) : (
<S.JobSelectButton
key={job}
onPress={() => setSelectedJob(job)}
$selected={isSelected(job)}
style={[
Platform.OS === 'ios' && {
shadowColor: isSelected(job) ? 'rgba(26, 117, 255, 0.20)' : 'rgba(0, 0, 0, 0.05)',
shadowOffset: {
width: 0,
height: isSelected(job) ? 0 : 1,
},
shadowOpacity: 1,
shadowRadius: isSelected(job) ? 6 : 10,
},
Platform.OS === 'android' && {
elevation: 0.5,
},
]}>
<Typography
variant='Body1/Normal'
fontWeight='medium'>
{job}
</Typography>
</S.JobSelectButton>
)
)}
</S.JobList>
<S.ButtonSection>
<SolidButton
full
size='large'
onPress={handleSaveJob}>
완료
</SolidButton>
</S.ButtonSection>
</S.Container>
);
}

export default JOB;

const S = {
Container: styled.View`
flex: 1;
padding: 30px 20px 0;
background-color: ${({ theme }) => theme.color.Background.Alternative};
`,
JobList: styled.View`
gap: 12px;
margin-top: 34px;
`,
JobSelectButton: styled.Pressable<{ $selected: boolean }>`
justify-content: center;
height: 64px;
padding: 20px 16px;
background-color: ${({ theme, $selected }) =>
$selected ? theme.color.Blue[95] : theme.color.Common[100]};
border-color: ${({ theme, $selected }) =>
$selected ? theme.color.Primary.Normal : theme.color.Line.Neutral};
border-width: 1px;
border-radius: 8px;
`,
ButtonSection: styled.View`
${flexDirectionColumnCenter}
position: absolute;
right: 0;
bottom: 0;
left: 0;
padding: 12px 20px 52px;
`,
InputContainer: styled.View`
height: 64px;
padding: 20px 16px;
background-color: ${({ theme }) => theme.color.Blue[95]};
border-color: ${({ theme }) => theme.color.Primary.Normal};
border-width: 1px;
border-radius: 8px;
`,
TextInput: styled.TextInput`
flex: 1;
font-size: 16px;
outline-width: 0;
`,
};
50 changes: 50 additions & 0 deletions app/(app)/my/policy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import styled from '@emotion/native';

import SolidButton from '@/components/common/button/SolidButton';
import Typography from '@/components/common/typography';
import { useTabBarEffect } from '@/hooks';
import { flexDirectionColumnCenter } from '@/styles/common';
import { theme } from '@/styles/theme';

function Policy() {
useTabBarEffect();

return (
<S.Container>
<S.ButtonSection>
<SolidButton
size='large'
full>
계속 이용하기
</SolidButton>
<Typography
style={{ textAlign: 'center' }}
variant='Body1/Normal'
color={theme.color.Label.Alternative}
breakWord>
탈퇴하기
</Typography>
</S.ButtonSection>
</S.Container>
);
}

export default Policy;

const S = {
Container: styled.View`
flex: 1;
padding: 23px 20px 0;
color: ${({ theme }) => theme.color.Label.Normal};
background-color: ${({ theme }) => theme.color.Background.Alternative};
`,
ButtonSection: styled.View`
${flexDirectionColumnCenter}
position: absolute;
right: 0;
bottom: 0;
left: 0;
gap: 8px;
padding: 12px 20px 30px;
`,
};
13 changes: 0 additions & 13 deletions app/(app)/my/profile.tsx

This file was deleted.

Loading

0 comments on commit 557f77b

Please sign in to comment.