// Screens 1-4: Landing, Explore, Detail, Compare
const { useState: useS1, useEffect: useE1, useRef: useR1 } = React;
const A = window.MajorAtoms;
const D = window.MajorLinkData;
const Lc = window.lucideReact || {};
// ============ SCREEN 1: LANDING ============
function ScreenLanding({ device, animKey }) {
const isM = device === 'mobile';
return (
{/* Top nav */}
{!isM && (
window.__nav && window.__nav.go('explore')}>둘러보기가이드 window.__nav && window.__nav.go('pricing')}>요금제FAQ
)}
{!isM && }
{/* Hero */}
2026년 7월 정식 출시
전공이 다르면,
팀이 강해집니다.
역할 기반 매칭 점수로
흩어진 전공을 하나의 프로젝트로 잇다.
{['이수민','박서연','정현우','한지우'].map(n =>
)}
1,247명의 학생이 사용 중
·
312개 프로젝트 진행
{/* Live demo card */}
{/* Section 2 — features */}
{D.FEATURES.map((f, i) => (
{f.id}
0{i+1}
{f.title}
{f.desc}
))}
{/* Section 3 — flow */}
HOW IT WORKS
가입에서 포트폴리오까지 6단계
{D.FLOW.map((s, i) => (
{s.n}
{!isM && i < D.FLOW.length - 1 &&
}
{s.title}
{s.desc}
))}
{/* Section 4 — projects preview */}
LIVE PROJECTS
지금 모집 중인 프로젝트
{!isM &&
}
{D.PROJECTS.slice(0, 3).map(p =>
)}
{/* Footer */}
전공 기반 대학생 협업 플랫폼 · 2026.07 정식 출시
{Object.keys(D.MAJOR).map(k => {
const m = D.MAJOR[k];
return {k};
})}
);
}
function LiveMatchDemo({ animKey, compact }) {
// auto-cycling 0→87
const [tick, setTick] = useS1(0);
useE1(() => {
const id = setInterval(() => setTick(t => t + 1), 3500);
return () => clearInterval(id);
}, []);
const k = animKey + tick;
const breakdown = { role: 30, skill: 22, period: 18, interest: 12, folio: 5 };
return (
);
}
// ============ Project card ============
function ProjectCard({ project, compact, withMatch }) {
const overdue = project.dday <= 7;
return (
window.__nav && window.__nav.go('detail', { projectId: project.id })}
className="rounded-2xl bg-white border p-4 relative shadow-card hover:shadow-cardHov transition cursor-pointer hover:-translate-y-0.5"
style={{ borderColor: '#E4E4E7' }}>
{withMatch && project.match >= 70 && (
🎯 {project.match}% 매칭
)}
{project.category}
D-{project.dday}
{project.title}
{project.desc}
{['프론트엔드','디자이너','PM'].slice(0, compact ? 2 : 3).map(r =>
{r})}
{project.filled}/{project.total}명
);
}
// ============ SCREEN 2: EXPLORE ============
function ScreenExplore({ device, animKey }) {
const isM = device === 'mobile';
return (
{isM ? (
{/* Mobile filter chips */}
{['역할 ▾','전공 ▾','기간 ▾','마감 ▾','인원 ▾'].map(c => (
))}
총 34개 프로젝트
{['최신','임박','매칭'].map((s,i)=>(
{s}
))}
{D.PROJECTS.map((p,i) =>
)}
) : (
프로젝트 탐색
총 34개 프로젝트 · 매칭 추천 4개
{['최신순','마감 임박순','매칭 추천순'].map((s,i)=>(
{s}
))}
{D.PROJECTS.map((p,i) =>
)}
)}
);
}
function FilterSidebar() {
return (
);
}
function FilterGroup({ title, items, type, defaultIdx }) {
return (
{title.toUpperCase()}
{type === 'check' && (
{items.map(it => (
))}
)}
{type === 'majors' && (
{Object.keys(D.MAJOR).map((k, i) => {
const m = D.MAJOR[k];
const on = i < 2;
return (
{k}
);
})}
)}
{type === 'select' && (
{items[defaultIdx ?? 0]}
)}
{type === 'radio' && (
{items.map((l, i) => (
{l}
))}
)}
{type === 'slider' && (
)}
);
}
// ============ SCREEN 3: PROJECT DETAIL ============
function ScreenDetail({ device, animKey, projectId }) {
const isM = device === 'mobile';
const project = D.PROJECTS.find(p => p.id === projectId) || D.PROJECTS[0];
const myScore = 76;
return (
{project.category}
D-{project.dday} 마감
{project.title}
{[
{ l: '기간', v: project.period },
{ l: '마감', v: '2026.06.15' },
{ l: '인원', v: `${project.filled}/${project.total}명` },
{ l: '방식', v: project.meeting },
].map(x => (
))}
한양대 학생 5,000명을 대상으로 분실물 매칭 서비스를 만듭니다. 사진을 올리면 AI가 유사 분실물과 자동으로 연결하고,
학교 위치 기반으로 가까운 사람에게 알림이 가요. 1차 MVP는 8주 안에 출시 목표.
디자인은 모바일 우선, 백엔드는 가벼운 Node.js + S3 이미지 저장. 디자인-개발-기획이 함께 사용자 인터뷰부터 같이 진행합니다.
{D.ROLES_NEEDED.map((r, i) => (
0{i+1}
{r.role}
{i === 0 ? '모집중' : `0/${r.count}`}
우대 · {r.pref}
))}
{['React','TypeScript','Tailwind','Figma','Node.js','PostgreSQL','AWS S3','GitHub'].map(t =>
{t})}
"이전에 두 번 사이드 프로젝트를 했는데 한 번도 디자이너랑 같이 못 했어요. 이번엔 디자인부터 같이 시작해서 진짜 출시까지 가보고 싶어요. 한양 분실물 카톡방 보면서 만들고 싶다고 생각한 지 1년 됐어요."
{/* Right rail (desktop) */}
{!isM && (
{D.LEADER.name}
{D.LEADER.school} · {D.LEADER.dept} {D.LEADER.year}학년
이전 프로젝트 {D.LEADER.priorProjects}건
지원 후 24시간 내 팀장이 응답합니다
)}
{/* Mobile sticky bar */}
{isM && (
)}
);
}
function MyMatchPreview({ score, animKey }) {
const breakdown = { role: 26, skill: 16, period: 18, interest: 12, folio: 4 };
return (
지원하면
상위 32%
비슷한 점수: 12명 / 38명
점수 올리는 방법
기술 스택을 더 등록하면 +9점, 포트폴리오 1개 추가하면 +5점
);
}
// ============ SCREEN 4: APPLICANT COMPARE ============
function ScreenCompare({ device, animKey, projectId }) {
const isM = device === 'mobile';
const [mode, setMode] = useS1('list'); // list | top3
const project = D.PROJECTS.find(p => p.id === projectId) || D.PROJECTS[0];
// shuffle applicants based on project id so each project shows different applicants
const seed = (project.id || 1) - 1;
const sorted = [...D.APPLICANTS]
.map((a, i) => ({ ...a, score: Math.max(45, Math.min(98, a.score + ((i + seed) % 5) * 3 - 6)) }))
.sort((a, b) => b.score - a.score);
return (
window.__nav && window.__nav.go('detail', { projectId: project.id })} />
{project.title}
지원자 {sorted.length}명 · 마감 D-{project.dday}
{!isM && (
{['점수순','최신순'].map((s,i)=>(
{s}
))}
)}
{!isM && (
{mode === 'list' ? (
) : (
)}
)}
{isM && (
{['점수순','최신순'].map((s,i)=>(
{s}
))}
← 거절 / 승인 →로 스와이프
{sorted.slice(1, 4).map((a, i) =>
)}
)}
);
}
function ApplicantCard({ applicant: a, animKey, index }) {
const col = A.scoreColor(a.score);
return (
window.__openApplicant && window.__openApplicant(a)}
className="rounded-2xl bg-white border p-5 grid grid-cols-12 gap-5 shadow-card hover:shadow-cardHov transition stagger-card cursor-pointer"
style={{ borderColor: '#E4E4E7', animationDelay: `${index * 50}ms` }}
>
{a.intro}
{a.skills.slice(0, 5).map(s =>
{s})}
{a.portfolio}
);
}
function ApplicantCardMobile({ applicant: a, animKey, compact }) {
const col = A.scoreColor(a.score);
if (compact) {
return (
window.__openApplicant && window.__openApplicant(a)} className="rounded-2xl bg-white border p-3.5 flex items-center gap-3 shadow-card cursor-pointer" style={{ borderColor: '#E4E4E7' }}>
{col.label}
);
}
return (
window.__openApplicant && window.__openApplicant(a)} className="rounded-2xl bg-white border p-5 shadow-cardHov stagger-card cursor-pointer" style={{ borderColor: '#E4E4E7' }}>
{col.label}
{a.intro}
{a.skills.slice(0, 4).map(s =>
{s})}
);
}
function Top3Compare({ applicants, animKey }) {
const rows = A.BREAKDOWN_LABELS;
const maxByRow = {};
rows.forEach(r => {
maxByRow[r.key] = Math.max(...applicants.map(a => a.breakdown[r.key]));
});
return (
가장 높은 항목은 Lime으로 표시
비교 항목
{applicants.map((a, i) => (
))}
{rows.map(row => (
{row.label} · /{row.max}
{applicants.map(a => {
const v = a.breakdown[row.key];
const isMax = v === maxByRow[row.key];
return (
);
})}
))}
한 줄 자기소개
{applicants.map(a => (
{a.intro}
))}
주요 기술
{applicants.map(a => (
{a.skills.slice(0,3).map(s =>
{s})}
))}
이 조합으로 팀 구성
최도윤 · 이수민 · 박서연 — 평균 매칭 86.7점
);
}
// ============ SCREEN: PRICING ============
function ScreenPricing({ device, animKey }) {
const isM = device === 'mobile';
return (
{/* Top nav (shared) */}
{!isM && (
window.__nav && window.__nav.go('explore')}>둘러보기가이드요금제FAQ
)}
{!isM && }
PRICING
팀에 맞는 플랜을 선택하세요
매칭 자체는 항상 무료입니다
{D.PRICING.map(plan => {
const highlight = plan.tone === 'indigo';
return (
{plan.name}
{plan.badge &&
{plan.badge}}
{plan.price}
{plan.sub}
{plan.note &&
{plan.note}
}
{plan.items.map(it => (
{it}
))}
);
})}
프로토타입 단계 가격안 · 확정 매출 아님
);
}
window.MajorScreens = {
ScreenLanding, ScreenExplore, ScreenDetail, ScreenCompare, ScreenPricing,
};