o2o-site-AEO/solution/frontend/src/features/builder/canvas/variants/intro/IntroSideBySide.tsx
김성경 a093921b62 feat(backend,site): NOL 수집 및 숙박 안내 구조화와 지역 콘텐츠 연동
수집한 객실·이용 정보가 발행 화면에 연결되지 않던 경로를 보완하고, 숙소 소개와 지역 맛집 표시를 개선한다.

- NOL 브라우저 수집 어댑터와 수집·반영 스크립트 추가
- 크롤링 fact 즉시 노출 및 직접 입력·정정값 보호
- 이용안내 항목별 구조화와 기존 표 연결, 원문 UI 비표시
- 군산 한일옥 고정 등록과 지역 맛집 탐색·보강 경로 추가
- 숙소 소개 요약, 히어로 문구, 지역 콘텐츠·목업 표시 개선

검증: 작업 트리 기준 site 타입·린트·빌드 및 안내 렌더링 테스트 통과, PC·모바일 화면 확인. 스테이징 diff 공백 검사 통과. 사용자 요청에 따라 현재 스테이징된 55개 파일만 포함하며 미스테이징 문서·테스트 등은 제외.
2026-09-14 19:40:04 +09:00

52 lines
2.0 KiB
TypeScript

/**
* 소개 · 사진 옆 글 — 왼쪽 세로 사진, 오른쪽 문단 + 특징 목록.
* 사진과 설명을 같은 눈높이에서 함께 읽히고 싶을 때.
*/
import {EmptyStateNotice, SectionBody, SectionFrame, SectionHeading} from '../../primitives';
import type {SectionRenderProps} from '../../types';
import {primaryPhoto, introParagraph, introSummary} from '../common';
export function IntroSideBySide(props: SectionRenderProps) {
const intro =
props.section.body?.trim() ||
introSummary(props.industryId, props.infoFields) ||
introParagraph(props.industryId, props.infoFields);
const {section, isSelected, onSelect, storeName, template, photos} = props;
const shot = photos[1] ?? primaryPhoto(photos);
// 사진이 없으면 회색 판만 남기고 <img> 는 렌더하지 않는다.
const shotUrl = shot?.url;
return (
<SectionFrame section={section} isSelected={isSelected} onSelect={onSelect} tone="paper">
<SectionBody>
<SectionHeading
variant="eyebrow"
eyebrow="ABOUT"
title={section.name}
subtitle={section.description}
/>
<div className="grid grid-cols-1 items-center gap-6 md:grid-cols-12">
<div className="md:col-span-5">
<div className="relative aspect-3/4 overflow-hidden rounded-2xl border border-stone-200/80 bg-stone-100">
{shotUrl && (
<img src={shotUrl} alt={`${storeName} 공간`} className="size-full object-cover" />
)}
</div>
</div>
<div className="space-y-4 md:col-span-7">
{intro ? (
<p className="text-xs leading-relaxed text-stone-700 sm:text-sm">{intro}</p>
) : (
<EmptyStateNotice>
아직 소개문이 없습니다 — 확인된 정보만 근거로 씁니다.
</EmptyStateNotice>
)}
</div>
</div>
</SectionBody>
</SectionFrame>
);
}