Kiosk Product · React · Vite · Supabase · Tailwind

RC Kiosk

헌혈의 집에서 헌혈자가 직접 기념품을 고르는 셀프 키오스크와, 그 운영을 한 곳에서 관리하는 관리자 백오피스. 두 앱은 동일한 Supabase DB를 공유하는 하나의 제품이다 — 관리자가 비활성화한 기념품은 즉시 키오스크에서 사라진다.

역할
개인 프로젝트 — 키오스크(사용자) + 백오피스(관리자) 전부 단독 설계/구현
공통 스택
React 18 · Vite · TypeScript · Tailwind CSS · Supabase · Firebase Hosting
백엔드
Supabase (gift_items, donation_locations, location_gift_items, gift_records, user_auth)
라우팅
HashRouter — 지점별 단축 URL /#/location/{locationId}
레포
a7garden/rc-kiosk-app · a7garden/rc-kiosk-admin-app

1. 화면

왼쪽은 헌혈자가 보는 키오스크, 오른쪽은 직원이 보는 관리자 백오피스. 같은 데이터, 다른 관점.

RC Kiosk 사용자 키오스크 — 진행 단계 사이드바, A/B 그룹 기념품 그리드, 이름 입력
사용자 키오스크 — 서울센터 헌혈의 집 진입 화면. A 3품목 + B 1품목 표시, 선택 기준 / 이름 입력 영역. URL /#/location/loc-001
RC Kiosk 사용자 키오스크 — A 1개 + B 1개 선택 후 이름 입력 단계
사용자 키오스크 — A 1개 + B 1개 선택 후 이름 입력 단계. 선택된 기념품 칩과 이름 입력란 동시 표시
RC Kiosk 관리자 백오피스 — 키오스크 링크/QR 관리, 지점별 활성화 토글
관리자 백오피스 — 기본 탭(기념품 키오스크). 5개 지점의 QR 카드 + 지점별 URL/QR 다운로드
RC Kiosk 관리자 백오피스 — 선택 기록(AdminRecords) 화면
관리자 백오피스 — 선택 기록 탭. 헌혈자 이름 / 선택 기념품 / 위치 / 시각을 표로 조회
RC Kiosk 관리자 백오피스 — 기념품 일괄 관리(BulkItemManager) 화면
관리자 백오피스 — 기념품 일괄 관리 탭. 지점별 / 전 지점 공통 기념품 등록·정렬

2. 문제

기존에는 헌혈자가 기념품을 고르면 직원이 종이로 받아 적고, 기록은 엑셀로 수동 관리했다. 헌혈의 집마다 기념품 구성이 다르고, A/B 그룹(단일 선택 vs 다중 선택) 정책도 달라 현장마다 매번 설명·기록이 반복됐다. 이걸 키오스크로 자동화하되, 운영자가 지점·기념품을 직접 통제할 수 있는 백오피스를 함께 만들었다.

3. 사용자 키오스크 (rc-kiosk-app)

3.1 동작 흐름

  1. 지점 식별 — 단축 URL의 locationIddonation_locations 조회, 지점명 표시.
  2. 기념품 목록 로드gift_items에서 해당 지점에 활성화(visible=true)된 항목만 필터. 카테고리(A/B), 정렬순서, 다중 선택 가능 여부까지 모두 DB에서.
  3. 선택 → 검증 — 카테고리별 1개(A 그룹) / 다중(B 그룹) 정책 적용.
  4. 이름 입력 → 제출 — 선택 기록을 gift_records에 저장.

3.2 화면별 구현 디테일

4. 관리자 백오피스 (rc-kiosk-admin-app)

4.1 MainLayout (사이드바)

4개 탭 — 선택자(selector) / 선택 기록(records) / 일괄 아이템(bulkItems) / 로그인(login). 활성 탭을 localStorage에 저장해 새로고침 시에도 유지. 키보드 포커스 트랩 + ESC 닫기 등 접근성 처리.

4.2 AdminRecords

헌혈자가 제출한 선택 기록 조회. 지점·날짜·지급 상태 필터, 일괄 삭제·지급 토글.

4.3 BulkItemManager

기념품 다중 등록/수정. react-beautiful-dnd로 카테고리·정렬 순서 드래그 편집. 이미지 선택 시 ImageSelectorModal로 미리보기/업로드.

4.4 GlobalItemManager

전 지점 공통 vs 지점별 기념품 분리 관리. 지점 활성화/비활성화 토글.

4.5 KioskLinks

qrcode.react로 각 지점 단축 URL의 QR을 즉시 생성 — 포스터에 인쇄해서 지점에 붙인다.

4.6 통계 (StatisticsModal)

기념품별 선택 수 집계. 대시보드 KPI와 일관되게 표시.

4.7 UX 디테일

5. 공유 데이터 모델

두 앱은 같은 5개 테이블을 공유한다. 지점·기념품·지점별 매핑·선택기록·인증이 분리되어 있어 양쪽이 항상 동기화된다.

gift_items {
  id, name, image_url, description,
  category: "A" | "B",
  sort_order, allow_multiple, visible
}

donation_locations {
  id, name  -- 키오스크 단축 URL 진입점
}

location_gift_items {
  location_id, gift_item_id  -- 지점별 기념품 매핑
}

gift_records {
  id, location_id, item_ids, donor_name, created_at
}

user_auth {
  id, password_hash  -- 관리자 인증 (백오피스)
}

관리자가 비활성화한 기념품은 즉시 키오스크에서 사라진다 — 별도 캐시 없이. Tailwind 색상 토큰은 적십자 팬톤 팔레트(redCrossRed, redCrossWarmGray, redCrossGold, redCrossGray, redCrossSilver) 5종을 사용해 시각 일관성을 유지했다.

6. 배포

7. 레포지토리