Skip to content

Commit

Permalink
#78 feat: validate onboarding (#95)
Browse files Browse the repository at this point in the history
* #78 feat: add password validation

* #78 feat: limit uploadable file conditions

* #78 chore: fix git merge error
  • Loading branch information
eujin-shin authored Jul 20, 2024
1 parent 0b9be3b commit 38d9871
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 50 deletions.
2 changes: 1 addition & 1 deletion node_modules/react-native/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"react-native-bouncy-checkbox": "^3.0.7",
"react-native-collapsible-tab-view": "^6.2.1",
"react-native-date-picker": "^5.0.0",
"react-native-document-picker": "^9.1.1",
"react-native-document-picker": "^9.3.0",
"react-native-dotenv": "^3.4.9",
"react-native-dropdown-picker": "^5.4.6",
"react-native-gesture-handler": "^2.15.0",
Expand Down
95 changes: 72 additions & 23 deletions src/common/FileBox.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { View, TextInput, TextStyle, StyleSheet } from 'react-native';
import {
View,
TextInput,
TextStyle,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import styled from 'styled-components/native';
import { BLACK2 } from '../styles/GlobalColor';
import { BLACK, BLACK2 } from '../styles/GlobalColor';
import { Body14M } from '../styles/GlobalText';
import PlusIcon from '../assets/common/Plus.svg';
import RightArrowIcon from '../assets/common/RightArrow.svg';
import DownArrowIcon from '../assets/common/DownArrow.svg';
import DeleteIcon from '../assets/header/Close.svg';

import FilePicker from './FilePicker';
import { Files } from '../types/UserTypes';

export interface FileBoxProps {
data: any[];
data: Files;
setData: (r: Files) => void;
max: number;
}

Expand All @@ -26,36 +34,77 @@ const SelectView = styled.View`
margin-bottom: 5px;
`;

const FileBox = ({ data, max }: FileBoxProps) => {
const FileBox = ({ data, setData, max }: FileBoxProps) => {
const handleFileDelete = (index: number) => {
const newData = data.filter((v, i) => i !== index);
setData(newData);
};

return (
<SelectView>
<FilePicker
callback={r => {}}
disabled={data.length >= max}
style={styles.BoxView}>
{data.length >= max ? (
<Body14M>더 이상 추가할 수 없습니다.</Body14M>
) : (
<>
<Body14M style={{ color: BLACK2 }}>추가해 주세요</Body14M>
<PlusIcon color={BLACK2} />
</>
)}
</FilePicker>
</SelectView>
<View>
<SelectView>
<FilePicker
callback={r => {
console.log(r);
setData([{ name: r.name ? r.name : 'noname', uri: r.uri }]);
}}
disabled={data.length >= max}
style={styles.BoxView}>
{data.length >= max ? (
<Body14M style={{ color: BLACK2 }}>
더 이상 추가할 수 없습니다
</Body14M>
) : (
<View style={styles.ItemView}>
<Body14M style={{ color: BLACK2 }}>추가해 주세요</Body14M>
<PlusIcon color={BLACK2} />
</View>
)}
</FilePicker>
</SelectView>
<View style={styles.ListView}>
{data.map((v, index) => {
return (
<View key={index} style={styles.ItemView}>
<Body14M style={{ color: BLACK }}>{v.name}</Body14M>
<TouchableOpacity onPress={() => handleFileDelete(index)}>
<DeleteIcon color={BLACK2} />
</TouchableOpacity>
</View>
);
})}
</View>
</View>
);
};

const styles = StyleSheet.create({
BoxView: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
justifyContent: 'center',
alignItems: 'center',
width: '100%',
height: 44,
paddingLeft: 16,
paddingRight: 16,
gap: 10,
},
ListView: {
display: 'flex',
alignItems: 'center',
width: '100%',
height: 44,
paddingLeft: 16,
paddingRight: 16,
marginTop: 10,
gap: 15,
},
ItemView: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
},
});

Expand Down
20 changes: 12 additions & 8 deletions src/common/FilePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
import { ReactNode } from 'react';
import { TouchableOpacity, ViewStyle } from 'react-native';
import { Alert, TouchableOpacity, ViewStyle } from 'react-native';
import {
DocumentPickerOptions,
DocumentPickerResponse,
pick,
types,
isCancel,
} from 'react-native-document-picker';

interface FilePickerProps {
style?: ViewStyle;
children?: any;
options?: DocumentPickerOptions<'android' | 'ios'>;
callback: (r: DocumentPickerResponse) => void;
disabled: boolean;
}

const FilePicker = ({
children,
style,
options,
callback,
disabled,
}: FilePickerProps) => {
const MEGABYTE = 1000000;

const handleFile = async () => {
try {
const [selectedFile] = await pick(options);
callback(selectedFile);
const [selectedFile] = await pick({ type: [types.pdf] });
if (selectedFile.size !== null && selectedFile.size > 20 * MEGABYTE) {
Alert.alert('크기 제한을 초과하는 파일입니다.');
} else {
callback(selectedFile);
}
} catch (e: unknown) {
console.log(e);
if (!isCancel(e)) Alert.alert('파일 업로드에 실패했습니다.');
}
};

Expand Down
4 changes: 4 additions & 0 deletions src/common/InputView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface InputViewProps extends InputBoxProps {
info?: string;
caption?: {
none?: false | string;
default?: false | string;
invalid?: false | string;
};
}
Expand Down Expand Up @@ -73,6 +74,9 @@ const InputView = ({
{value === '' && caption?.none && (
<Caption11M style={{ color: GRAY }}>{caption.none}</Caption11M>
)}
{caption?.default && (
<Caption11M style={{ color: GRAY }}>{caption.default}</Caption11M>
)}
{caption?.invalid && (
<Caption11M style={{ color: PURPLE }}>{caption.invalid}</Caption11M>
)}
Expand Down
26 changes: 19 additions & 7 deletions src/components/Auth/BasicForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,26 @@ export default function BasicForm({ navigation, route }: FormProps) {
d: false,
});
const [checkPw, setCheckPw] = useState('');
const [domainOpen, setDomainOpen] = useState(false);
const [invalidPw, setInvalidPw] = useState<undefined | boolean>(undefined);
const [modalOpen, setModalOpen] = useState(false);
const [splash, setSplash] = useState(false);

const request = Request();
const passwordRegExp = new RegExp(
'^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,15}$',
);

const passwordValidation = (callback: () => void) => {
if (passwordRegExp.exec(form.password)) {
callback();
} else {
Alert.alert('비밀번호가 올바르지 않습니다.');
setForm(prev => {
return { ...prev, password: '' };
});
setCheckPw('');
}
};

const handleSubmit = async () => {
const params = {
Expand Down Expand Up @@ -199,11 +214,8 @@ export default function BasicForm({ navigation, route }: FormProps) {
style={{ height: 44, marginTop: 8 }}
secure={true}
caption={{
none: '비밀번호 조건',
invalid:
form.password !== '' &&
form.password.length < 7 &&
'비밀번호가 올바르지 않습니다.',
default:
'숫자, 영문, 특수문자를 하나 이상 포함해 8자 이상 16자 이하로 설정해 주세요.',
}}
/>

Expand Down Expand Up @@ -303,7 +315,7 @@ export default function BasicForm({ navigation, route }: FormProps) {
}
value="다음"
pressed={false}
onPress={handleSubmit}
onPress={() => passwordValidation(handleSubmit)}
style={{
width: '75%',
alignSelf: 'center',
Expand Down
14 changes: 11 additions & 3 deletions src/components/Auth/Reformer/CareerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default function CareerModal({
const handleContentChange = (v: any, t: string) => {
const prevCareer = form.career;
prevCareer[index] = { ...prevCareer[index], [t]: v };
// console.log(prevCareer[index]);
console.log(prevCareer[index]);
setForm(prev => {
return { ...prev, career: prevCareer };
});
Expand Down Expand Up @@ -357,9 +357,17 @@ export default function CareerModal({
<View
style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
<Body16B>증빙자료첨부</Body16B>
<Caption11M style={{ color: BLACK2 }}>선택사항</Caption11M>
<Caption11M style={{ color: BLACK2 }}>
선택사항 (pdf, 최대 20MB)
</Caption11M>
</View>
<FileBox data={form.career[index].file} max={1} />
<FileBox
data={form.career[index].file}
setData={r => {
handleContentChange(r, 'file');
}}
max={1}
/>
</View>

<View style={{ marginTop: 'auto' }}>
Expand Down
10 changes: 7 additions & 3 deletions src/types/UserTypes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
type Styles = '빈티지' | '미니멀' | '캐주얼';
type Materials = '가죽' | '스웨이드' | '벨벳' | '데님' | '퍼' | '실크' | '울';
type File = any[];
interface File {
name: string;
uri: string;
}
export type Files = File[];

export type StyleType = Styles[];
export type MaterialType = Materials[];
Expand All @@ -9,13 +13,13 @@ export type EducType = {
school: string;
major: string;
status: string | undefined;
file: File;
file: Files;
// 파일 형식 추가
};

export type Careers = {
name: string;
file: File;
file: Files;
type: string | undefined;
team?: string;
position?: string;
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6522,10 +6522,10 @@ react-native-date-picker@^5.0.0:
resolved "https://registry.npmjs.org/react-native-date-picker/-/react-native-date-picker-5.0.0.tgz"
integrity sha512-ApTKpZocalFCDMfczY34ugo85oQJfYO4VKqAxrtSFolzJdUqIJXa8ot0PIINokVI1O2X2L5hLboeqrM84GNfpQ==

react-native-document-picker@^9.1.1:
version "9.1.1"
resolved "https://registry.npmjs.org/react-native-document-picker/-/react-native-document-picker-9.1.1.tgz"
integrity sha512-BW+7DbsILuFThlBm7NUFVUmKKf6Awkcf9R0q8wiCU2DlGGtAKQTt2iHpO5+Dn/7WMPB+rqNv3X1HsmJQ0t5R3g==
react-native-document-picker@^9.3.0:
version "9.3.0"
resolved "https://registry.yarnpkg.com/react-native-document-picker/-/react-native-document-picker-9.3.0.tgz#4651d354623367d06397fe6dbf4a496f7d92ca6b"
integrity sha512-X/j0xKn8cObckpHTNwE/hW9WzBiP6oKx820FYu1Nat43QnnHmmT6uozFgAUDcJfxmZGcEdLlbv0lNhnyRXJyyA==
dependencies:
invariant "^2.2.4"

Expand Down

0 comments on commit 38d9871

Please sign in to comment.