/* global React */
function Placeholder({
ratio = "3 / 2",
label,
tone = "blue",
radius = "var(--yj-radius-large)",
}) {
// Non-infringing image placeholder; evokes JW.org's blue-gray illustration palette
// without reproducing any actual artwork.
const palettes = {
blue: ["#4a6da7", "#8aa3c9", "#d8e1ee"],
warm: ["#8b6b4a", "#c9a98a", "#eedec6"],
indigo: ["#3a4a7a", "#7388b7", "#cfd6e6"],
slate: ["#52606d", "#9aa5b1", "#cbd2d9"],
teal: ["#2f6b6e", "#78a6a8", "#cde0e0"],
sand: ["#b08a5b", "#d6b98a", "#f0dfc2"],
night: ["#1d2a44", "#3d5280", "#7388b7"],
};
const [a, b, c] = palettes[tone] || palettes.blue;
return (
);
}
function Chevron({ size = 12 }) {
return (
);
}
/* ---------- Landing motion graphic ---------- */
function MotionHero() {
return (
);
}
/* ---------- Featured Memorial banner ---------- */
const BANNER_VIDEO = "videos/banner.mp4";
function MemorialBanner() {
const [hasVideo, setHasVideo] = React.useState(true);
return (
{/* 배경 동영상 */}
{hasVideo ? (
) : (
)}
{/* 어두운 오버레이 */}
{/* 텍스트 */}
추천
양정 회중에 오신 것을
환영합니다.
부산 대도시캠페인 양정회중
더 알아보기
);
}
/* ---------- 추천 자료 (3-up feature row) ---------- */
const FEATURED = [];
const WMO_ICON = (code) => {
if (code === 0) return "☀️";
if (code <= 2) return "⛅";
if (code === 3) return "☁️";
if (code <= 48) return "🌫️";
if (code <= 55) return "🌦️";
if (code <= 65) return "🌧️";
if (code <= 77) return "🌨️";
if (code <= 82) return "🌦️";
if (code <= 86) return "🌨️";
return "⛈️";
};
const WMO_DESC = (code) => {
if (code === 0) return "맑음";
if (code <= 2) return "구름 조금";
if (code === 3) return "흐림";
if (code <= 48) return "안개";
if (code <= 55) return "이슬비";
if (code <= 65) return "비";
if (code <= 77) return "눈";
if (code <= 82) return "소나기";
if (code <= 86) return "눈 소나기";
return "천둥번개";
};
const DAY_KO = ["일", "월", "화", "수", "목", "금", "토"];
function WeatherCard() {
const [data, setData] = React.useState(null);
const [error, setError] = React.useState(false);
const [view, setView] = React.useState("hourly");
React.useEffect(() => {
fetch(
"https://api.open-meteo.com/v1/forecast?latitude=35.18&longitude=129.07" +
"¤t_weather=true" +
"&hourly=temperature_2m,weathercode,precipitation_probability,relativehumidity_2m,apparent_temperature" +
"&daily=weathercode,temperature_2m_max,temperature_2m_min,precipitation_probability_max" +
"&timezone=Asia%2FSeoul&forecast_days=7",
)
.then((r) => r.json())
.then((d) => {
const cur = d.current_weather;
const nowStr = cur.time.slice(0, 13);
const nowIdx = d.hourly.time.findIndex((t) => t.startsWith(nowStr));
const baseIdx = nowIdx >= 0 ? nowIdx : 0;
const humidity = d.hourly.relativehumidity_2m[baseIdx] ?? "—";
const feels = Math.round(
d.hourly.apparent_temperature[baseIdx] ?? cur.temperature,
);
const hourly = d.hourly.time
.slice(baseIdx, baseIdx + 24)
.map((t, i) => ({
time: t,
hour: new Date(t).getHours(),
temp: Math.round(d.hourly.temperature_2m[baseIdx + i]),
code: d.hourly.weathercode[baseIdx + i],
rain: d.hourly.precipitation_probability[baseIdx + i] ?? 0,
isCurrent: i === 0,
}));
const daily = d.daily.time.map((date, i) => ({
date,
code: d.daily.weathercode[i],
max: Math.round(d.daily.temperature_2m_max[i]),
min: Math.round(d.daily.temperature_2m_min[i]),
rain: d.daily.precipitation_probability_max[i],
}));
setData({ cur, humidity, feels, hourly, daily });
})
.catch(() => setError(true));
}, []);
const TabBtn = ({ id, label }) => (
);
return (
{error ? (
날씨 정보를 불러올 수 없습니다.
) : !data ? (
날씨 불러오는 중…
) : (
<>
{/* 현재 날씨 */}
{WMO_ICON(data.cur.weathercode)}
{Math.round(data.cur.temperature)}°C
{WMO_DESC(data.cur.weathercode)}
체감 {data.feels}°
습도 {data.humidity}%
풍속 {data.cur.windspeed}㎞/h
{view === "hourly" ? (
/* 시간대별 예보 — 주간과 동일한 7칸 그리드 */
{data.hourly.slice(0, 7).map((h) => {
const isNextDay = !h.isCurrent && h.hour === 0;
return (
{h.isCurrent
? "지금"
: isNextDay
? "내일"
: h.hour + "시"}
{WMO_ICON(h.code)}
{h.temp}°
{h.rain > 0 && (
💧{h.rain}%
)}
);
})}
) : (
/* 주간 예보 */
{data.daily.map((d, i) => {
const dayName =
i === 0
? "오늘"
: i === 1
? "내일"
: DAY_KO[new Date(d.date).getDay()] + "요일";
return (
{dayName}
{WMO_ICON(d.code)}
{d.max}°
{d.min}°
{d.rain > 0 && (
💧{d.rain}%
)}
);
})}
)}
>
)}
);
}
function FeaturedSection() {
return (
);
}
/* ---------- Online Bible promo (dark cinematic) ---------- */
function BiblePromo() {
return (

{
e.target.style.display = "none";
}}
/>
양정구역 · 추천자료
양정회중 구역을 알아보세요.
양정회중 구역은 넓고 다양한 매력을 품고 있어요. 부산의 대표적인
번화가부터, 편한 신발이 필수인 고바위 주택가까지 다양하답니다.
);
}
/* ---------- Topics grid (어떤 주제에 관심이 가십니까?) ---------- */
function TopicImage({ tone, title, image }) {
const [failed, setFailed] = React.useState(false);
if (image && !failed) {
return (
setFailed(true)}
style={{
width: "100%",
aspectRatio: "1/1",
objectFit: "cover",
display: "block",
}}
/>
);
}
return ;
}
const TOPICS = [
{
title: "추천카페",
tone: "blue",
image: "images/main/topic-1.jpeg",
href: "#/맛집/카페",
},
{
title: "추천맛집",
tone: "warm",
image: "images/main/topic-2.jpeg",
href: "#/맛집/우정",
},
{
title: "부산 가볼만한 곳",
tone: "indigo",
image: "images/main/topic-3.jpeg",
href: "#/맛집/부산관광",
},
{
title: "의료정보",
tone: "sand",
image: "images/main/topic-4.jpeg",
href: "#/안내/정보2",
},
];
function TopicsSection() {
return (
);
}
function ActionsSection() {
return null;
}
/* ---------- Videos carousel ---------- */
const VIDEOS = [
{
title: "나보다 나이가 많은 사람과 친구가 될 수 있을까?",
sub: "어떻게 나이가 많은 사람과 친구가 될 수 있는지 알아보세요.",
tone: "teal",
image: "images/tour/out-bong.jpeg",
noPlay: true,
},
{
title: "화장실 비번을 기억하십시오",
tone: "night",
video: "videos/toilet.mp4",
},
{ title: "양정회중 귀욤이들?", tone: "slate" },
{ title: "가족 체육대회", tone: "indigo" },
{ title: "사진 4", tone: "warm" },
{ title: "사진 5", tone: "blue" },
{ title: "사진 6", tone: "sand" },
{ title: "사진 7", tone: "night" },
];
function PlayBadge() {
return (
);
}
function VideosSection() {
const scrollerRef = React.useRef(null);
const [modal, setModal] = React.useState(null);
const scroll = (dir) => {
const el = scrollerRef.current;
if (!el) return;
el.scrollBy({ left: dir * el.clientWidth * 0.8, behavior: "smooth" });
};
return (
{modal && (
setModal(null)}
style={{
position: "fixed",
inset: 0,
zIndex: 9999,
background: "rgba(0,0,0,0.88)",
display: "flex",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
}}
>
e.stopPropagation()}
style={{ width: "min(92vw, 860px)" }}
>
{modal.title}
)}
);
}
/* ---------- About JW long-copy section ---------- */
function AboutSection() {
return (
양정회중 가족들은 어떤 사람들입니까?
부산 양정회중 가족들은 매우 다양한 연령대,성격,취미,직업을 지닌
사람들로 이루어져 있지만, 연합하여 동일한 목표를 추구합니다. 우리는
성경에 나오는 하느님이자 모든 것의 창조주이신 여호와를 영예롭게 하는
일을 가장 중요하게 생각합니다.

{
e.currentTarget.style.display = "none";
}}
/>
);
}
/* ---------- Footer ---------- */
const FOOTER_COLS = [
{
title: "맛집-핫플",
items: [
{ label: "맛집", href: "#/맛집/우정" },
{ label: "카페", href: "#/맛집/카페" },
{ label: "구역근처 명소", href: "#/맛집/구역내명소" },
{ label: "구역외 명소", href: "#/맛집/추천관광" },
],
},
{
title: "안내",
items: [{ label: "의료 정보", href: "#/안내/정보2" }],
},
];
function Footer() {
return (
);
}
Object.assign(window, {
Placeholder,
Chevron,
MotionHero,
MemorialBanner,
FeaturedSection,
BiblePromo,
TopicsSection,
ActionsSection,
VideosSection,
AboutSection,
Footer,
});