diff --git a/Front-end/src/components/institution/RequestKid.tsx b/Front-end/src/components/institution/RequestKid.tsx index 2955211..afac095 100644 --- a/Front-end/src/components/institution/RequestKid.tsx +++ b/Front-end/src/components/institution/RequestKid.tsx @@ -8,11 +8,61 @@ interface RequestKidProps { index: number; } -const RequestKid = (props: RequestKidProps) => { - console.log(props); - return test; +const RequestKid: React.FC = ({ name, gender, birth, index }) => { + return ( + + {index + 1} + + {name} + + {birth} + {gender} + + + + ); }; export default RequestKid; -const Container = styled.button``; +const KidContainer = styled.div` + display: flex; + align-items: center; + padding: 10px; + margin: 5px 0; + background-color: #f8f8f8; + border-radius: 8px; +`; + +const KidIndex = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 30px; + height: 30px; + margin-right: 15px; + background-color: #e1e1e1; + border-radius: 50%; + font-weight: bold; +`; + +const KidInfo = styled.div` + flex-grow: 1; +`; + +const KidName = styled.div` + font-size: 1rem; + font-weight: bold; + margin-bottom: 5px; +`; + +const KidDetails = styled.div` + font-size: 0.9rem; + color: #666; +`; + +const KidBirth = styled.span` + margin-right: 10px; +`; + +const KidGender = styled.span``; diff --git a/Front-end/src/db/firestore.ts b/Front-end/src/db/firestore.ts index afb9798..e427fec 100644 --- a/Front-end/src/db/firestore.ts +++ b/Front-end/src/db/firestore.ts @@ -1,5 +1,5 @@ -import { initializeApp, FirebaseApp } from 'firebase/app'; -import { getFirestore } from 'firebase/firestore'; +import { initializeApp, getApps, getApp } from 'firebase/app'; +import { getFirestore, Firestore } from 'firebase/firestore'; // Firebase const firebaseConfig = { @@ -12,12 +12,16 @@ const firebaseConfig = { measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID, }; -export const initialization = () => { - try { - const app: FirebaseApp = initializeApp(firebaseConfig); - const db = getFirestore(app); - return { app, db }; - } catch (e) { - console.log('initialization : ', e); +let app; +let db; + +export const initialization = (): Firestore => { + if (!getApps().length) { + app = initializeApp(firebaseConfig); + db = getFirestore(app); + } else { + app = getApp(); + db = getFirestore(app); } + return db; }; diff --git a/Front-end/src/db/query.ts b/Front-end/src/db/query.ts index 8fa13ee..e2e7d6a 100644 --- a/Front-end/src/db/query.ts +++ b/Front-end/src/db/query.ts @@ -14,7 +14,7 @@ export async function withFirestore(operation: (db: Firestore) => Promise) if (!initializationResult) { throw new Error('Database initialization failed'); } - const { db } = initializationResult; + const db = initializationResult; return operation(db); } catch (error) { console.error(error); diff --git a/Front-end/src/pages/institution/RegistrationRequest.tsx b/Front-end/src/pages/institution/RegistrationRequest.tsx index dbc731a..fce0352 100644 --- a/Front-end/src/pages/institution/RegistrationRequest.tsx +++ b/Front-end/src/pages/institution/RegistrationRequest.tsx @@ -2,10 +2,11 @@ import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import fonts from 'constants/fonts'; +import { RegistrationItem } from 'utils/type'; // DB -import { firestore } from '../../utils/firestore'; -import { onSnapshot, query, collection } from 'firebase/firestore'; +import { initialization } from 'db/firestore'; +import { query, collection, onSnapshot } from 'firebase/firestore'; // Component import Header from 'components/Header'; @@ -15,48 +16,48 @@ import RequestKid from 'components/institution/RequestKid'; import { useRecoilValue } from 'recoil'; import { institutionState } from '../../recoil/institutionState'; -interface RegistrationItem { - birth: string; - gender: string; - institution: string; - isRegistered?: boolean; - name: string; +interface StyledSelected { + selected: boolean; } const RegistrationRequest = ({ hasGoback = true }) => { const institution = useRecoilValue(institutionState); const [realTimeRequest, setRealTimeRequest] = useState([]); - const q = query(collection(firestore, 'institution', `${institution.name}`, 'RegistrationRequest')); + const [selectedKids, setSelectedKids] = useState>(new Set()); const navigate = useNavigate(); + const db = initialization(); const goBackHandler = () => { navigate(-1); }; + const toggleSelection = (index: number) => { + setSelectedKids((prevSelected) => { + const newSelected = new Set(prevSelected); + if (newSelected.has(index)) { + newSelected.delete(index); + } else { + newSelected.add(index); + } + return newSelected; + }); + }; + useEffect(() => { - const unsubscribe = onSnapshot( - q, - (querySnapshot) => { - const requests: RegistrationItem[] = []; - - querySnapshot.forEach((doc) => { - const data: RegistrationItem = doc.data() as RegistrationItem; - if (data) { - requests.push(data); - } + const fetchRealTimeRequests = () => { + const realTimeRequestsQuery = query(collection(db, 'institution', institution.name, 'RegistrationRequest')); + onSnapshot(realTimeRequestsQuery, (snapshot) => { + const realTimeRequestList = snapshot.docs.map((doc) => { + const { birth, gender, institution, name } = doc.data(); + console.log(doc.data()); + return { birth, gender, institution, name }; }); - - setRealTimeRequest(requests); - }, - (err) => { - console.log('TODO: error 처리 일관화', err); - }, - ); - - return () => { - unsubscribe(); + setRealTimeRequest(realTimeRequestList); + }); }; - }, [q]); + + fetchRealTimeRequests(); + }, [db, institution.name]); return ( @@ -67,12 +68,10 @@ const RegistrationRequest = ({ hasGoback = true }) => { {realTimeRequest.length === 0 ? null : realTimeRequest?.map((kid: RegistrationItem, i: number) => ( -
-
- {kid.name} {kid.gender} {kid.birth} -
+ toggleSelection(i)}> -
+ + ))}
); @@ -105,3 +104,25 @@ const HeaderContainer = styled.div` align-items: center; padding: 16px; `; + +const KidContainer = styled.div` + display: flex; + align-items: center; + background-color: ${({ selected }) => (selected ? '#E0F7FA' : 'transparent')}; + transition: background-color 0.3s; + cursor: pointer; + + &:hover { + background-color: #e0f7fa; + } +`; + +const SelectionIndicator = styled.div` + width: 20px; + height: 20px; + border: 2px solid #009688; + border-radius: 50%; + margin-left: auto; + background-color: ${({ selected }) => (selected ? '#009688' : 'transparent')}; + transition: background-color 0.3s; +`; diff --git a/Front-end/src/utils/type.ts b/Front-end/src/utils/type.ts index b713364..dcb3fbe 100644 --- a/Front-end/src/utils/type.ts +++ b/Front-end/src/utils/type.ts @@ -24,3 +24,11 @@ type requestKidInfo = { isRegistered: boolean; name: string; }; + +export interface RegistrationItem { + birth: string; + gender: string; + institution: string; + isRegistered?: boolean; + name: string; +}