Skip to content

Commit

Permalink
#25 feat: add quotation form
Browse files Browse the repository at this point in the history
  • Loading branch information
SJ-Kwak authored Feb 1, 2024
1 parent 748c70f commit 4b02f00
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/assets/common/Check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/common/Photo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions src/common/CheckBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { View, TouchableOpacity, ViewStyle } from 'react-native';
import Check from '../assets/common/Check.svg';
import { PURPLE } from '../styles/GlobalColor';
import { Body14M } from '../styles/GlobalText';

interface CheckBoxProps {
pressed: boolean;
onPress: () => void;
text: string;
style?: ViewStyle
}

const CheckBox = ({ pressed, onPress, text, style }: CheckBoxProps) => {
return (
<View style={{flexDirection: 'row', ...style}}>
<TouchableOpacity
onPress={onPress}
style={{
width: 20,
height: 20,
borderWidth: 1,
borderColor: PURPLE,
backgroundColor: pressed ? PURPLE : 'white',
alignItems: 'center',
justifyContent: 'center'
}}
>
<Check />
</TouchableOpacity>
<Body14M style={{marginLeft: 10}}>{text}</Body14M>
</View>
)
}

export default CheckBox;
31 changes: 31 additions & 0 deletions src/common/Filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import styled from 'styled-components/native';
import { BLACK, PURPLE } from '../styles/GlobalColor';
import { Filter14M } from '../styles/GlobalText';

interface FilterProps {
value: string;
pressed: boolean;
onPress: () => void;
}

const Filter = ({ value, pressed, onPress }: FilterProps) => {
return (
<FilterContainer pressed={pressed} onPress={onPress}>
<Filter14M style={{color: pressed ? 'white' : BLACK}}>{value}</Filter14M>
</FilterContainer>
)
}

const FilterContainer = styled.TouchableOpacity<{ pressed: boolean }>`
display: flex;
padding: 6px 16px;
justify-content: center;
align-items: center;
margin-bottom: 8px;
margin-right: 10px;
border-radius: 12px;
border: 1px solid ${PURPLE};
background: ${(props: { pressed: boolean; }) => props.pressed ? PURPLE : 'white'};
`

export default Filter;
33 changes: 33 additions & 0 deletions src/common/InputBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Dispatch, SetStateAction } from 'react';
import { TextInput } from 'react-native';
import { BLACK2 } from '../styles/GlobalColor';

interface InputBoxProps {
value: string;
setValue: Dispatch<SetStateAction<string>>;
placeholder: string;
long?: boolean;
}

const InputBox = ({ value, setValue, placeholder, long }: InputBoxProps) => {
return (
<TextInput
value={value}
onChangeText={setValue}
placeholder={placeholder}
placeholderTextColor={BLACK2}
multiline={long}
style={{
width: '100%',
height: 100,
borderWidth: 1,
borderColor: BLACK2,
borderRadius: 5,
paddingHorizontal: 16,
paddingTop: 10
}}
/>
)
}

export default InputBox;
146 changes: 146 additions & 0 deletions src/components/Home/Quotation/QuotationForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { SetStateAction, useState, Dispatch } from 'react';
import { ScrollView, View, Text, TouchableOpacity, ImageBackground } from 'react-native';
import styled from 'styled-components/native';
import { BLACK, LIGHTGRAY, PURPLE } from '../../../styles/GlobalColor';
import { Body14M, Body16M, Caption11M, Caption12M, Subtitle16B, Subtitle18B, Subtitle18M, Title20B } from '../../../styles/GlobalText';
import { getStatusBarHeight } from 'react-native-safearea-height';

import Filter from '../../../common/Filter';
import InputBox from '../../../common/InputBox';
import BottomButton from '../../../common/BottomButton';
import CheckBox from '../../../common/CheckBox';

import { StackScreenProps } from '@react-navigation/stack';
import { HomeStackParams } from '../../../pages/Home';

import Arrow from '../../../assets/common/Arrow.svg';
import Search from '../../../assets/common/Search.svg';
import Photo from '../../../assets/common/Photo.svg';

const statusBarHeight = getStatusBarHeight(true);

interface FilterSectionProps {
label: string;
items: any[];
}

const FilterSection = ({ label, items }: FilterSectionProps) => {
return (
<FilterContainer>
<FilterBox style={{marginBottom: 5, justifyContent: 'space-between'}}>
<Subtitle18M>{label}</Subtitle18M>
<Caption11M style={{color: PURPLE}}>• 중복 가능</Caption11M>
</FilterBox>
<FilterBox>
{items.map((item, index) => (
<Filter key={index} value={item} pressed={false} onPress={() => {}} />
))}
</FilterBox>
</FilterContainer>
)
}

const QuotationForm = ({ navigation, route }: StackScreenProps<HomeStackParams, 'Quotation'>) => {
const materials = ['폴리에스테르', '면', '스웨이드', '울', '캐시미어', '가죽', '데님', '추가 요청사항에 기재']
const sizes = ['XS(85)', 'S(90)', 'M(95)', 'L(100)', 'XL(105)', 'XXL(110)']
const options = ['프릴 추가', '단추 추가', '지퍼 추가', '주머니 추가']
const [text, setText] = useState<string>('');

return (
<ScrollView>
<BackButton onPress={() => navigation.goBack()}>
<Arrow color={'white'} />
</BackButton>
<SearchButton>
<Search />
</SearchButton>
<ImageBackground
source={{uri: 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp'}}
style={{width: '100%', height: 210}}
>
<View style={{position: 'absolute', width: '100%', height: '100%', backgroundColor: BLACK, opacity: 0.7}} />
<View style={{paddingTop: 100, paddingLeft: 50}}>
<Title20B style={{color: 'white', marginBottom: 3}}>마켓명 (SDP의 상점)</Title20B>
<Caption12M style={{color: 'white', marginBottom: 18}}>리폼러 닉네임 (전성식탁)</Caption12M>
<Body16M style={{color: 'white'}}>마켓 소개글</Body16M>
</View>
</ImageBackground>
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Subtitle16B style={{paddingVertical: 20}}>견적서 작성</Subtitle16B>
<PhotoButton style={{paddingVertical: 12}}>
<Photo />
<Body14M style={{marginLeft: 10}}>작업할 사진 첨부</Body14M>
</PhotoButton>
</View>
<View style={{height: 8, backgroundColor: '#F4F4F4'}} />
<FilterSection label='재질 선택' items={materials} />
<FilterSection label='희망 사이즈 선택' items={sizes} />
<FilterSection label='옵션 선택' items={options} />
<View style={{height: 8, backgroundColor: '#F4F4F4'}} />
<View style={{paddingHorizontal: 15, paddingVertical: 20, alignItems: 'flex-start', borderBottomWidth: 0.5, borderColor: '#D9D9D9'}}>
<Subtitle18M style={{marginBottom: 10}}>추가 요청사항</Subtitle18M>
<PhotoButton style={{paddingVertical: 6}}>
<Photo />
<Body14M style={{marginLeft: 10}}>참고 사진 첨부</Body14M>
</PhotoButton>
<InputBox value={text} setValue={setText} placeholder='입력해주세요' long />
</View>
<View style={{paddingHorizontal: 15, paddingVertical: 20, borderBottomWidth: 8, borderColor: '#F4F4F4'}}>
<Subtitle18M style={{marginBottom: 10}}>포트폴리오 사용 가능 여부</Subtitle18M>
<CheckBox style={{paddingHorizontal: 30, alignSelf: 'center'}} pressed={false} onPress={() => {}} text='리폼 제품이 서비스 내의 포트폴리오에 사용되는 것에 동의합니다.' />
</View>
<View style={{paddingHorizontal: 15, paddingVertical: 20}}>
<Subtitle18M style={{marginBottom: 10}}>거래 방식 선택</Subtitle18M>
<FilterBox style={{alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 80}}>
{['비대면', '대면'].map((item, index) => (
<Filter key={index} value={item} pressed={false} onPress={() => {}} />
))}
</FilterBox>
</View>
<View style={{paddingHorizontal: 45, paddingVertical: 20}}>
<BottomButton value='다음' pressed={false} onPress={() => {}} />
</View>
</ScrollView>
)
}

const BackButton = styled.TouchableOpacity`
padding: 10px;
position: absolute;
left: 0px;
top: ${statusBarHeight-10}px;
z-index: 1;
`

const SearchButton = styled.TouchableOpacity`
padding: 10px;
position: absolute;
right: 7px;
top: ${statusBarHeight-10}px;
z-index: 1;
`

const PhotoButton = styled.TouchableOpacity`
display: flex;
flex-direction: row;
align-items: center;
padding-horizontal: 16px;
background: ${LIGHTGRAY};
border-radius: 6px;
margin-bottom: 20px;
`

const FilterContainer = styled.View`
padding: 20px 15px;
border-bottom-width: 0.5px;
border-color: #D9D9D9;
`

const FilterBox = styled.View`
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
`

export default QuotationForm;
Empty file.
6 changes: 6 additions & 0 deletions src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import { TouchableOpacity } from 'react-native-gesture-handler';
import CustomHeader from '../common/CustomHeader';
import MarketTabView from '../components/Home/Market/MarketTabView';
import DetailPageScreen from '../components/Home/Market/DetailPage';
import QuotationForm from '../components/Home/Quotation/QuotationForm';

export type HomeStackParams = {
Home: undefined;
Market: undefined;
DetailPage: {
id?: number;
};
Quotation: undefined;
};

const HomeStack = createStackNavigator<HomeStackParams>();
Expand All @@ -36,6 +38,7 @@ const HomeScreen = ({
<HomeStack.Screen name='Home' component={HomeMainScreen} />
<HomeStack.Screen name='Market' component={MarketTabView} />
<HomeStack.Screen name='DetailPage' component={DetailPageScreen} />
<HomeStack.Screen name='Quotation' component={QuotationForm} />
</HomeStack.Navigator>
);
};
Expand All @@ -53,6 +56,9 @@ const HomeMainScreen = ({
<TouchableOpacity onPress={() => navigation.navigate('Market')}>
<Text>마켓</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('Quotation')}>
<Text>견적서</Text>
</TouchableOpacity>
</SafeAreaView>
);
};
Expand Down

0 comments on commit 4b02f00

Please sign in to comment.