feat: 헤더 매뉴얼 버튼 · 프로필 검색 · 상세 뒤로가기 뎁스 정리

- 헤더 프로필 왼쪽에 '매뉴얼' 버튼 추가(MANUAL_URL 환경변수, 기본 gitea MANUAL)
- 검색을 페이지 내 data-search 카드 전체 대상으로 일반화 → 프로필에서 그 사람
  프로젝트도 검색(자리표시자도 페이지별로: 공유/내/○○ 님의 프로젝트)
- 상세 페이지 뒤로가기: ?from= 내부경로 기반으로 프로필→상세는 프로필로 복귀
- '사내 개발 포털' +4pt, 도구 카드 이름·설명 +2pt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 15:43:32 +09:00
parent b512ab2143
commit 40f8352a28
10 changed files with 42 additions and 11 deletions

View File

@@ -31,6 +31,7 @@ app.use(
// 모든 뷰 공통 노출 (브랜드·사용자·뷰 헬퍼)
app.use((req, res, next) => {
res.locals.brand = config.brand;
res.locals.manualUrl = config.manualUrl;
res.locals.user = req.session.user || null;
res.locals.icon = icon;
res.locals.identicon = identicon;
@@ -124,7 +125,10 @@ app.get("/u/:sabun", requireAuth, async (req, res) => {
const profile = await db.getUserProfile(req.params.sabun);
if (!profile) return res.status(404).send("사용자를 찾을 수 없습니다.");
const projects = await db.listProjectsByOwner(profile.sabun, me);
res.render("profile", { profile, projects, isSelf: profile.sabun === me });
const searchPlaceholder = profile.sabun === me
? "내 프로젝트 검색…"
: `${profile.name} 님의 프로젝트 검색…`;
res.render("profile", { profile, projects, isSelf: profile.sabun === me, searchPlaceholder });
});
// --- 대시보드 ---
@@ -183,7 +187,14 @@ app.get("/projects/:id", requireAuth, async (req, res) => {
// 비공개는 본인만 열람
if (!project.is_public && project.owner_sabun !== me) return res.status(403).send("비공개 프로젝트입니다.");
const comments = await db.listComments(project.id);
res.render("project", { project, comments, starred: project.starred });
// 뒤로가기 대상: ?from= 으로 넘어온 내부 경로(프로필 등)가 있으면 그곳, 없으면 대시보드.
// (뎁스 순서: 프로필 → 프로젝트 상세 로 들어왔으면 프로필로 돌아간다)
const from = req.query.from;
const safeFrom = typeof from === "string" && /^\/[^/]/.test(from) ? from : null; // 내부 절대경로만 허용
const back = safeFrom && safeFrom.startsWith("/u/")
? { href: safeFrom, label: "프로필" }
: { href: "/", label: "대시보드" };
res.render("project", { project, comments, starred: project.starred, back });
});
// --- 반응: ❤️ 좋아요 / ⭐ 즐겨찾기 ---