Skip to content

Commit

Permalink
Feat/#60 QuestionnaireCheckListSkeleton을 추가합니다. (#62)
Browse files Browse the repository at this point in the history
* refactor: 폴더 구조를 변경합니다.

* feat: QuestionnaireCheckListSkeleton를 추가합니다.
  • Loading branch information
Zero-1016 authored Sep 25, 2024
1 parent 32417bf commit 1343149
Show file tree
Hide file tree
Showing 20 changed files with 297 additions and 48 deletions.
10 changes: 4 additions & 6 deletions app/(app)/project/create.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SimpleLineIcons } from '@expo/vector-icons';
import { AntDesign } from '@expo/vector-icons';
import type { BottomSheetModal } from '@gorhom/bottom-sheet';
import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';
import type { DateTimePickerEvent } from '@react-native-community/datetimepicker';
Expand Down Expand Up @@ -41,8 +41,6 @@ function Create() {

const sheetHeight = useMemo(() => getSize.screenHeight * 0.75, []);

const snapPoints = useMemo(() => [sheetHeight], []);

const openUserListSheet = useCallback(() => {
setUserListSheetOpen(true);
userListBottomSheetRef.current?.snapToIndex(0);
Expand Down Expand Up @@ -182,8 +180,8 @@ function Create() {
<S.UserListSheetOpenButtonContainer>
<InputField
icon={
<SimpleLineIcons
name='magnifier'
<AntDesign
name='search1'
style={{ flexShrink: 1, width: 20, height: 20 }}
size={20}
/>
Expand Down Expand Up @@ -249,7 +247,7 @@ function Create() {
ref={userListBottomSheetRef}
index={-1}
enablePanDownToClose
snapPoints={snapPoints}>
snapPoints={[sheetHeight]}>
<BottomSheetView style={{ flex: 1 }}>
{userListSheetOpen && (
<SearchUserList
Expand Down
12 changes: 7 additions & 5 deletions src/components/common/date-input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ function DateInput({ onPress, date }: Props) {
<S.Container
style={shadow[2]}
onPress={onPress}>
<AntDesign
name='calendar'
size={24}
color='#979797'
/>
<S.IconBox>
<AntDesign
name='calendar'
size={20}
color='#979797'
/>
</S.IconBox>
<Typography>{dayjs(date).format('YYYY-MM-DD')}</Typography>
</S.Container>
);
Expand Down
4 changes: 4 additions & 0 deletions src/components/common/date-input/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ export const Container = styled.Pressable`
background: ${({ theme }) => theme.color.Background.Normal};
border-radius: 8px;
`;

export const IconBox = styled.View`
${flexDirectionRowItemsCenter};
`;
53 changes: 53 additions & 0 deletions src/components/common/icon/radio-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Svg, { Circle, Rect } from 'react-native-svg';

type Props = {
activeColor: string;
inActiveColor: string;
isChecked: boolean;
};

function RadioIcon({ activeColor, inActiveColor, isChecked }: Props) {
if (isChecked) {
return (
<Svg
width='16'
height='17'
viewBox='0 0 16 17'
fill='none'>
<Circle
cx='7.95894'
cy='8.49752'
r='7.29'
stroke={activeColor}
stroke-width='1.215'
/>
<Circle
cx='7.95894'
cy='8.49775'
r='4.05'
fill={activeColor}
/>
</Svg>
);
} else {
return (
<Svg
width='16'
height='16'
viewBox='0 0 16 16'
fill='none'>
<Rect
x='0.668945'
y='0.807617'
width='14.58'
height='14.58'
rx='7.29'
stroke={inActiveColor}
stroke-width='1.215'
/>
</Svg>
);
}
}

export default RadioIcon;
4 changes: 2 additions & 2 deletions src/components/common/input-field/style.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import styled, { css } from '@emotion/native';
import type { Theme } from '@emotion/react';

import { flexDirectionRow } from '@/styles/common';
import { flexDirectionRow, flexDirectionRowItemsCenter } from '@/styles/common';

const errorStyle = (theme: Theme) => css`
border-color: ${theme.color.Status.Error};
Expand All @@ -24,7 +24,7 @@ export const Container = styled.View<{
}>`
${({ $isError, theme }) => $isError && errorStyle(theme)};
${({ $disabled, theme }) => $disabled && disabledStyle(theme)};
${flexDirectionRow};
${flexDirectionRowItemsCenter};
gap: 8px;
padding: 18px 16px;
background-color: ${({ theme }) => theme.color.Background.Normal};
Expand Down
80 changes: 80 additions & 0 deletions src/components/questionnaire/QuestionnaireCheckList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { PropsWithChildren } from 'react';
import { useContext, useState } from 'react';
import { createContext } from 'react';
import { memo } from 'react';

import RadioIcon from '@/components/common/icon/radio-icon';
import Typography from '@/components/common/typography';
import { color } from '@/styles/theme';
import type { CategoryType } from '@/types/category';

import CategoryChip from '../category-chip';
import * as S from './style';

type ItemProps = {
value: string | number;
};

const ListContext = createContext<{
checkValue: string | null | number;
setCheckValue: (newValue: string | null | number) => void;
}>({
checkValue: null,
setCheckValue: () => null,
});

function Item({ children, value }: PropsWithChildren<ItemProps>) {
const { checkValue, setCheckValue } = useContext(ListContext);
const isChecked = checkValue === value;
return (
<S.ItemContainer $isChecked={isChecked}>
<S.ItemValue>{children}</S.ItemValue>
<S.RadioButton onPress={() => setCheckValue(value)}>
<RadioIcon
activeColor={color.Primary.Normal}
inActiveColor={color.Line.Normal}
isChecked={isChecked}
/>
</S.RadioButton>
</S.ItemContainer>
);
}

type QuestionnaireCheckListProps = {
title: string;
category: CategoryType;
initialCheckValue?: string | number;
};

function CheckList({
title,
category,
initialCheckValue,
children,
}: PropsWithChildren<QuestionnaireCheckListProps>) {
const [checkValue, setCheckValue] = useState<null | string | number>(() =>
initialCheckValue ? initialCheckValue : null
);
return (
<ListContext.Provider
value={{
checkValue,
setCheckValue,
}}>
<S.Container>
<CategoryChip category={category} />
<Typography
variant='Heading1'
fontWeight='semiBold'
color={color.Label.Normal}>
{title}
</Typography>
<S.ListContainer>{children}</S.ListContainer>
</S.Container>
</ListContext.Provider>
);
}

const QuestionnaireCheckList = Object.assign(CheckList, { Item: memo(Item) });

export default QuestionnaireCheckList;
49 changes: 49 additions & 0 deletions src/components/questionnaire/QuestionnaireCheckList/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import styled, { css } from '@emotion/native';
import type { Theme } from '@emotion/react';

import { flexDirectionColumn, flexDirectionRowItemsCenter } from '@/styles/common';

export const Container = styled.View`
${flexDirectionColumn};
gap: 20px;
width: 272px;
padding: 28px 16px;
background: ${({ theme }) => theme.color.Background.Normal};
border-radius: 13px;
`;

const inActiveStyle = (theme: Theme) => css`
background: ${theme.color.Background.Normal};
border: 1px solid ${theme.color.Line.Normal};
`;

const activeStyle = (theme: Theme) => css`
background: ${theme.color.Blue['95']};
border: 1px solid ${theme.color.Primary.Normal};
`;

export const ItemContainer = styled.View<{ $isChecked: boolean }>`
${flexDirectionRowItemsCenter};
${({ theme, $isChecked }) => ($isChecked ? activeStyle(theme) : inActiveStyle(theme))};
justify-content: space-between;
padding: 13px 28px 13px 13px;
border-radius: 7px;
`;

export const ListContainer = styled.View`
${flexDirectionColumn};
gap: 8px;
`;

export const ItemValue = styled.View`
${flexDirectionColumn};
`;

export const RadioButton = styled.Pressable`
${flexDirectionRowItemsCenter};
position: absolute;
top: 0;
right: 0;
height: 100%;
padding: 13px;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Meta, StoryObj } from '@storybook/react';
import { View } from 'react-native';

import { color } from '@/styles/theme';

import QuestionnaireCheckListSkeleton from './';

const SkeletonMeta: Meta<typeof QuestionnaireCheckListSkeleton> = {
title: 'questionnaire/QuestionnaireCheckListSkeleton',
component: QuestionnaireCheckListSkeleton,
parameters: {
layout: 'centered',
},
};

export default SkeletonMeta;

export const Primary: StoryObj<typeof QuestionnaireCheckListSkeleton> = {
render: () => {
return (
<View style={{ flex: 1, backgroundColor: color.Background.Alternative, padding: 10 }}>
<QuestionnaireCheckListSkeleton />
</View>
);
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Skeleton from '@/components/common/skeleton';
import QuestionnaireCheckList from '@/components/questionnaire/QuestionnaireCheckList';

import * as S from './style';

function SkeletonItem() {
return (
<S.SkeletonBox>
<Skeleton
variant='rounded'
width='60%'
height={14}
/>
<Skeleton
variant='rounded'
width='30%'
height={14}
/>
</S.SkeletonBox>
);
}

function QuestionnaireCheckListSkeleton() {
return (
<QuestionnaireCheckList
title='프로님은 회의 중 의견을 나눌때 어땠나요?'
category='기술'>
<QuestionnaireCheckList.Item value={0}>
<SkeletonItem />
</QuestionnaireCheckList.Item>
<QuestionnaireCheckList.Item value={1}>
<SkeletonItem />
</QuestionnaireCheckList.Item>
<QuestionnaireCheckList.Item value={2}>
<SkeletonItem />
</QuestionnaireCheckList.Item>
<QuestionnaireCheckList.Item value={3}>
<SkeletonItem />
</QuestionnaireCheckList.Item>
</QuestionnaireCheckList>
);
}

export default QuestionnaireCheckListSkeleton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from '@emotion/native';

import { flexDirectionColumnCenter } from '@/styles/common';

export const SkeletonBox = styled.View`
${flexDirectionColumnCenter};
gap: 4px;
`;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Meta, StoryObj } from '@storybook/react';

import CategoryChip from '@/components/common/category-chip/index';
import Storybook from '@/components/common/storybook';
import CategoryChip from '@/components/questionnaire/category-chip/index';

const CategoryChipMeta: Meta<typeof CategoryChip> = {
title: 'category/CategoryChip',
title: 'questionnaire/CategoryChip',
component: CategoryChip,
argTypes: {
category: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Meta, StoryObj } from '@storybook/react';

import Category from '@/components/common/category/index';
import Storybook from '@/components/common/storybook';
import Category from '@/components/questionnaire/category/index';

const CategoryMeta: Meta<typeof Category> = {
title: 'category/Category',
title: 'questionnaire/Category',
component: Category,
argTypes: {
category: {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const Container = styled.View<{
`;

export const IconWrapper = styled.View`
${flexDirectionRowItemsCenter};
width: 24px;
height: 24px;
`;
Loading

0 comments on commit 1343149

Please sign in to comment.