Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/images/guide_image_1.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/guide_image_2.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/guide_image_3.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/guide_image_4.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/guide_image_5.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/guide_image_6.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/pages/guide/constants/guide-images.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const GUIDE_IMAGES = [
{ id: 1, src: 'images/guide_image_1.webp', alt: '가이드 1' },
{ id: 2, src: 'images/guide_image_2.webp', alt: '가이드 2' },
{ id: 3, src: 'images/guide_image_3.webp', alt: '가이드 3' },
{ id: 4, src: 'images/guide_image_4.webp', alt: '가이드 4' },
{ id: 5, src: 'images/guide_image_5.webp', alt: '가이드 5' },
{ id: 6, src: 'images/guide_image_6.webp', alt: '가이드 6' },
] as const;
Comment on lines +1 to +8
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

이미지 상수 정의 적절하나 접근성/경로 확인 권장

  • alt가 모두 “가이드 N”으로 동일해 스크린 리더 유용성이 낮습니다. 정보 전달용이면 더 구체적으로, 장식용이면 alt를 빈 문자열로 처리하고 컴포넌트에서 aria-hidden 고려를 권장합니다.
  • src 경로가 'images/...' 상대 경로입니다. 빌드/배포 환경(Vite/CRA 등)에서 public 경로 기준인지 절대경로('/images/...')가 필요한지 확인해 주세요.

이미지 자산 존재와 로딩 경로를 점검하는 스크립트입니다.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "[1] 이미지 자산 존재 확인"
fd -HI 'guide_image_*.webp' | sed -e 's/^/  /'

echo "[2] 가이드 페이지에서 alt/role 사용 확인"
rg -nC3 -g "src/**" -P "GUIDE_IMAGES|<img|alt=|aria-hidden" src/pages/guide/guide.tsx || true

echo "[3] 빌드 시 public 경로 사용 여부 점검(일반적인 패턴)"
rg -nC2 -g "src/**" -P "/images/guide_image_\\d+\\.webp|new URL\\(" 

Length of output: 1849


이미지 자산 미존재, 경로 및 접근성 문제 해결 필요

  • src/pages/guide/constants/guide-images.ts에서 참조하는 images/guide_image_*.webp 파일이 리포지토리에 없습니다.
  • 상대경로 images/...는 빌드 환경에서 /guide/.../images/... 등으로 잘못 해석될 수 있으니 public 기준 절대경로(/images/...)로 변경하거나 빌드 설정에서 경로 해석 방식을 검증하세요.
  • 현재 alt="가이드 N"이 aria-label(가이드 이미지 N / 6)과 중복되어 스크린리더에서 중복 안내가 발생합니다. 정보 전달용이면 더 구체적 설명, 장식용이면 alt=""aria-hidden 적용 바랍니다.
🤖 Prompt for AI Agents
In src/pages/guide/constants/guide-images.ts lines 1-8 the image entries
reference non-existent relative paths and use alt text that duplicates
aria-labels for screen readers; fix by moving/adding the image files into the
public/images folder (or whichever public/static dir your build expects) and
update each src to an absolute public path like /images/guide_image_X.webp, and
resolve accessibility duplication by either providing meaningful descriptive alt
text (e.g., "가이드 이미지 X — [short description]") if the image conveys information,
or marking them as decorative by setting alt="" and adding aria-hidden="true" at
the img usage site; ensure your changes match the app's image-loading
conventions (public paths vs imports) and update any consuming components to use
the new absolute paths and appropriate aria attributes.


export type GuideImage = (typeof GUIDE_IMAGES)[number];
56 changes: 56 additions & 0 deletions src/pages/guide/guide.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import CarouselIndicator from '@pages/match/groups/components/carousel_indicator';
import { useSlide } from '@pages/match/hooks/useSlide';
import { getSlideTransformStyle } from '@pages/match/styles/get-slide-transformstyle';
import { useState } from 'react';
import { GUIDE_IMAGES } from './constants/guide-images';

const Guide = () => {
const [currentIndex, setCurrentIndex] = useState(0);

const { handleTouchStart, handleTouchEnd, handleMouseDown } = useSlide({
length: GUIDE_IMAGES.length,
currentIndex,
onChange: setCurrentIndex,
});

return (
<section
className="w-full flex-col gap-[2.4rem] overflow-hidden "
aria-label="가이드 이미지 캐러셀"
>
<ul
className="flex pt-[3.2rem] transition-transform duration-300 ease-in-out"
style={getSlideTransformStyle(currentIndex)}
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
onMouseDown={handleMouseDown}
aria-roledescription="carousel"
aria-live="polite"
>
{GUIDE_IMAGES.map((image, index) => (
<li
key={image.id}
aria-roledescription="slide"
aria-label={`가이드 이미지 ${index + 1} / ${GUIDE_IMAGES.length}`}
aria-hidden={index !== currentIndex}
className="min-w-full px-[0.8rem]"
>
<div className="box-border min-w-full flex-row-center ">
<img src={image.src} alt={image.alt} className="h-auto w-full " />
</div>
</li>
))}
</ul>

<div className="flex-row-center">
<CarouselIndicator
ids={GUIDE_IMAGES.map((image) => `guide-${image.id}`)}
currentIndex={currentIndex}
onDotClick={setCurrentIndex}
/>
</div>
</section>
);
};

export default Guide;
14 changes: 13 additions & 1 deletion src/pages/home/components/top-section.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import CardBanner from '@components/card/banner-card/banner-card';
import { ROUTES } from '@routes/routes-config';
import { useNavigate } from 'react-router-dom';

const TopSection = () => {
const navigate = useNavigate();

const handleBannerClick = () => {
navigate(ROUTES.GUIDE);
};

return (
<section className="bg-gray-black px-[1.6rem] pt-[0.1rem]">
<CardBanner subText="나와 딱 맞는 직관 메이트를 찾고 싶다면?" text="이용가이드 보러 가기" />
<CardBanner
subText="나와 딱 맞는 직관 메이트를 찾고 싶다면?"
text="이용가이드 보러 가기"
onClick={handleBannerClick}
/>
</section>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ const BottomNavigation = () => {

const isActive = (path: string) => pathname === path;

const isDisabled = (path: string) => needsMatchingSetup && path !== ROUTES.HOME;
const isDisabled = (path: string) => {
return needsMatchingSetup && path !== ROUTES.HOME;
};

const handleTabClick = (path: string) => {
if (isDisabled(path)) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,12 @@ export const NAV_ITEMS = [
},
},
];

export type NavItem = {
label: string;
path: string;
icon: {
filled: string;
lined: string;
};
};
7 changes: 4 additions & 3 deletions src/shared/components/card/banner-card/banner-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ interface CardBannerProps {
text: string;
subText?: string;
className?: string;
onClick?: () => void;
}

const BannerCard = ({ text, subText, className }: CardBannerProps) => {
const BannerCard = ({ text, subText, onClick }: CardBannerProps) => {
return (
<div className={cn('relative w-full', className)}>
<button type="button" className={cn('relative cursor-pointer text-left')} onClick={onClick}>
<img src={BannerImg} alt="홈배너" className="w-full" />
<div className="absolute inset-0 flex-col justify-center gap-[0.4rem] py-[2.2rem] pl-[2.4rem]">
<p className="cap_14_m text-gray-800">{subText}</p>
<p className="subhead_18_sb text-gray-black">{text}</p>
</div>
</div>
</button>
);
};

Expand Down
8 changes: 7 additions & 1 deletion src/shared/constants/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ export const NO_HEADER_PATHS = [
ROUTES.CHAT,
];

export const SHOW_BOTTOM_NAVIGATE_PATHS = [ROUTES.HOME, ROUTES.MATCH, ROUTES.CHAT, ROUTES.PROFILE];
export const SHOW_BOTTOM_NAVIGATE_PATHS = [
ROUTES.HOME,
ROUTES.MATCH,
ROUTES.CHAT,
ROUTES.PROFILE,
ROUTES.GUIDE,
];
3 changes: 3 additions & 0 deletions src/shared/routes/lazy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export const SignUp = lazy(() => import('@pages/sign-up/sign-up'));
// Home
export const Home = lazy(() => import('@pages/home/home'));

// Guide
export const Guide = lazy(() => import('@pages/guide/guide'));

// Matching
export const Onboarding = lazy(() => import('@pages/onboarding/onboarding'));
export const OnboardingGroup = lazy(() => import('@pages/onboarding/onboarding-group'));
Expand Down
2 changes: 2 additions & 0 deletions src/shared/routes/protected-routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
EditProfile,
GroupMates,
GroupNew,
Guide,
Home,
Match,
Onboarding,
Expand All @@ -29,4 +30,5 @@ export const protectedRoutes = [
{ path: ROUTES.RESULT(), element: <Result /> },
{ path: ROUTES.ONBOARDING, element: <Onboarding /> },
{ path: ROUTES.ONBOARDING_GROUP, element: <OnboardingGroup /> },
{ path: ROUTES.GUIDE, element: <Guide /> },
];
1 change: 1 addition & 0 deletions src/shared/routes/routes-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export const ROUTES = {
ERROR: '/error',
LOADING: '/loading',
SPLASH: '/splash',
GUIDE: '/guide',
};