Skip to content

Commit

Permalink
feat: 도서관별 좌석 현황 페이지 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
eunbae0 committed Apr 15, 2024
1 parent aaec063 commit 2ff1a78
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 46 deletions.
20 changes: 4 additions & 16 deletions src/components/molecules/screens/announcement/list/ArticleList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {FlatList} from 'react-native-gesture-handler';
import {DefinedInfiniteQueryObserverResult} from '@tanstack/react-query';
import ArticleItem from './ArticleItem';
import {ArticleItemType} from '../../../../../types/announcement.type';
import usePullToRefresh from '../../../../../hooks/usePullToRefresh';

const REFRESH_STOP_TIME = 0.5 * 1000;

Expand All @@ -29,22 +30,9 @@ const ArticleList = forwardRef<FlatList, ArticleListProps>(
ref,
) => {
// pull to refresh
const [refreshing, setRefreshing] = useState(false);
const setRefreshFinish = () =>
setTimeout(() => {
setRefreshing(false);
}, REFRESH_STOP_TIME);

const onRefresh = useCallback(() => {
if (!refetch) return;
setRefreshing(true);
try {
refetch();
} catch (err) {
setRefreshFinish();
}
setRefreshFinish();
}, [refetch]);
const {onRefresh, refreshing} = usePullToRefresh(() =>
refetch ? refetch() : undefined,
);

// render item
const renderItem: ListRenderItem<any> = ({item}) => (
Expand Down
75 changes: 53 additions & 22 deletions src/components/molecules/screens/library/LibraryRoomItem.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,72 @@
import React from 'react';
import styled from '@emotion/native';
import styled, {css} from '@emotion/native';
import {Txt, colors} from '@uoslife/design-system';
import {useNavigation} from '@react-navigation/native';
import {LibraryStatusItemType} from '../../../../api/services/util/library/libraryAPI.type';
import boxShadowStyle from '../../../../styles/boxShadow';
import AnimatePress from '../../../animations/pressable_icon/AnimatePress';
import {LibraryRoomStatusNavigationProp} from '../../../../navigators/types/library';
import customShowToast from '../../../../configs/toast/index';

export type Props = {item: LibraryStatusItemType};
// TODO: 스터디홀, 중도 이외 도서관 예약 기능 추가되면 삭제
const ACCSS_RESTRICTION_ROOM_NUMBER = ['6', '21', '22', '32', '33'];

export type Props = {
item: LibraryStatusItemType;
boxWidth: number;
};

const LibraryRoomItem = ({item, boxWidth}: Props) => {
const navigation = useNavigation<LibraryRoomStatusNavigationProp>();
const isAccessRestriction = ACCSS_RESTRICTION_ROOM_NUMBER.some(
i => i === item.room_no,
);

const LibraryRoomItem = ({item}: Props) => {
return (
<S.Container>
<S.itemTxtContainer>
<Txt
label={`${item.room_name}`}
color="grey190"
typograph="titleSmall"
/>
<Txt
label={`잔여 ${item.remain_seat}석 / ${item.total_seat}석`}
color="grey130"
typograph="bodyLarge"
/>
</S.itemTxtContainer>
<AnimatePress
style={[
css`
display: flex;
margin: 6px;
padding: 20px 12px;
gap: 4px;
align-items: center;
border-radius: 12px;
background-color: ${colors.white};
flex: 1;
width: 100%;
`,
{...boxShadowStyle.bottomTapShadow, width: boxWidth / 2 - 22},
]}
variant={isAccessRestriction ? 'none' : 'scale_up_3'}
onPress={() => {
if (isAccessRestriction) {
customShowToast('preparingLibraryReservationInfo');
return;
}
navigation.navigate('Library_seat_list', {
roomNumber: item.room_no,
});
}}>
<Txt label={`${item.room_name}`} color="grey190" typograph="titleSmall" />
<Txt
label={`잔여 ${item.remain_seat}석 / ${item.total_seat}석`}
color="grey130"
typograph="bodyLarge"
/>
<S.progressBarConatiner>
<S.progressBarTrail>
<S.progressBarInner useRate={item.use_rate} />
</S.progressBarTrail>
</S.progressBarConatiner>
</S.Container>
</AnimatePress>
);
};

export default LibraryRoomItem;

const S = {
Container: styled.View`
display: flex;
padding: 12px 0;
gap: 4px;
`,
Container: styled.View``,
itemTxtContainer: styled.View`
display: flex;
flex-direction: row;
Expand All @@ -46,6 +76,7 @@ const S = {
progressBarConatiner: styled.View`
margin-top: 8px;
margin-bottom: 8px;
width: 100%;
`,
progressBarTrail: styled.View`
height: 4px;
Expand Down
39 changes: 39 additions & 0 deletions src/components/molecules/screens/library/LibraryRoomStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {useQuery} from '@tanstack/react-query';
import styled from '@emotion/native';
import {colors} from '@uoslife/design-system';
import {useState} from 'react';
import {UtilAPI} from '../../../../api/services';
import LibraryRoomItem from './LibraryRoomItem';
import usePullToRefresh from '../../../../hooks/usePullToRefresh';
import {LibraryRoomStatusTabsType} from '../../../../configs/utility/libraryTabs';

type Props = {roomType: LibraryRoomStatusTabsType};

const LibraryRoomStatus = ({roomType}: Props) => {
const {data, refetch} = useQuery({
queryKey: ['getLibraryRoomStatus', roomType],
queryFn: () => UtilAPI.getLibraryRoomStatus({type: roomType}),
});

const {onRefresh, refreshing} = usePullToRefresh(() => refetch());
const [width, setWidth] = useState(0);
return (
<S.Container
data={data?.item}
refreshing={refreshing}
onRefresh={onRefresh}
renderItem={({item}) => <LibraryRoomItem item={item} boxWidth={width} />}
numColumns={2}
onLayout={event => setWidth(event.nativeEvent.layout.width)}
/>
);
};

export default LibraryRoomStatus;

const S = {
Container: styled.FlatList`
padding: 8px 10px;
background-color: ${colors.primaryLighterAlt};
`,
};
12 changes: 12 additions & 0 deletions src/configs/utility/libraryTabs.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
export type LibraryTabsType = 'MY_SEAT' | 'SEAT_LIST' | 'RECORD';
export type LibraryTabsEnumType = Record<LibraryTabsType, string>;

export type LibraryRoomStatusTabsType = 'ECONOMY' | 'LAW' | 'CENTRAL';
export type LibraryRoomStatusTabsEnumType = Record<
LibraryRoomStatusTabsType,
string
>;

export const LibraryTabsEnum: LibraryTabsEnumType = {
MY_SEAT: '내자리',
SEAT_LIST: '좌석',
RECORD: '기록',
};

export const LibraryRoomStatusTabsEnum: LibraryRoomStatusTabsEnumType = {
CENTRAL: '중앙도서관',
LAW: '법학전문도서관',
ECONOMY: '경영경제도서관',
};
4 changes: 2 additions & 2 deletions src/navigators/types/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export type LibraryStackParamList = {
};

export type LibraryRoomStatusStackParamList = {
Library_room_status_main: {roomType: 'ECONOMY' | 'LAW' | 'CENTRAL'};
Library_seat_list: {roomNumber: number};
Library_room_status_main?: {roomType?: 'ECONOMY' | 'LAW' | 'CENTRAL'};
Library_seat_list: {roomNumber: string};
Library_portal_authentication: undefined;
};

Expand Down
1 change: 0 additions & 1 deletion src/screens/library/LibraryMainScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ const LibraryMainScreen = ({route: {params}}: LibraryMainScreenProps) => {
}, [isFocused, setIsFocusedLibraryScreen]);

return (
// <LibrarySeatStatus />
<>
<Header
label="도서관"
Expand Down
58 changes: 53 additions & 5 deletions src/screens/library/room_status/LibraryRoomStatusScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,62 @@
import {useMemo, useState} from 'react';
import {useNavigation} from '@react-navigation/native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {
LibraryRoomStatusTabsEnum,
LibraryRoomStatusTabsType,
} from '../../../configs/utility/libraryTabs';
import {LibraryRoomStatusScreenProps} from '../../../navigators/types/library';

import Header from '../../../components/molecules/common/header/Header';
import TabView from '../../../components/molecules/common/tab_view/TabView';
import LibraryRoomStatus from '../../../components/molecules/screens/library/LibraryRoomStatus';

const LibraryRoomStatusScreen = ({
route: {params},
}: LibraryRoomStatusScreenProps) => {
const initialRoomType = (params?.roomType ?? 'CENTRAL') satisfies
| 'ECONOMY'
| 'LAW'
| 'CENTRAL';
const insets = useSafeAreaInsets();
const navigation = useNavigation();
const handleGoBack = () => {
navigation.goBack();
};
const initialRoomType = (params?.roomType ??
'CENTRAL') satisfies LibraryRoomStatusTabsType;

const initialIndex = useMemo(
() =>
Object.keys(LibraryRoomStatusTabsEnum).findIndex(i =>
i.match(initialRoomType),
),
[initialRoomType],
);
const [index, setIndex] = useState(initialIndex);

return <></>;
return (
<>
<Header
label="도서관"
onPressBackButton={handleGoBack}
style={{paddingTop: insets.top}}
/>
<TabView index={index} setIndex={setIndex}>
<TabView.Screen
tabKey="CENTRAL"
tabTitle={LibraryRoomStatusTabsEnum.CENTRAL}
component={<LibraryRoomStatus roomType="CENTRAL" />}
/>
<TabView.Screen
tabKey="LAW"
tabTitle={LibraryRoomStatusTabsEnum.LAW}
component={<LibraryRoomStatus roomType="LAW" />}
/>
<TabView.Screen
tabKey="ECONOMY"
tabTitle={LibraryRoomStatusTabsEnum.ECONOMY}
component={<LibraryRoomStatus roomType="ECONOMY" />}
/>
</TabView>
</>
);
};

export default LibraryRoomStatusScreen;

0 comments on commit 2ff1a78

Please sign in to comment.