first commit
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
<script setup lang="ts">
|
||||
// 저장소 헤더 카드 — 상세/멤버/활동/설정 화면이 공유
|
||||
import { computed } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import type { Repo, User } from '@/mock/relay.mock'
|
||||
|
||||
interface Props {
|
||||
repo: Repo
|
||||
/** 메타 우측 텍스트(예: "2시간 전 업데이트", "멤버 5명") */
|
||||
metaText: string
|
||||
/** 아바타 스택 override (기본: repo.members) */
|
||||
members?: User[]
|
||||
/** +N 표기 (기본: repo.moreCount) */
|
||||
moreCount?: number
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const avatars = computed(() => props.members ?? props.repo.members)
|
||||
const extra = computed(() => props.moreCount ?? props.repo.moreCount)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="repo-head">
|
||||
<div class="repo-ico">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20" />
|
||||
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="rh-main">
|
||||
<div class="rh-title">
|
||||
<span class="rh-name">{{ repo.name }}</span>
|
||||
<span
|
||||
class="vis"
|
||||
:class="repo.visibility"
|
||||
>
|
||||
<svg
|
||||
v-if="repo.visibility === 'private'"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2.5"
|
||||
>
|
||||
<rect
|
||||
x="3"
|
||||
y="11"
|
||||
width="18"
|
||||
height="11"
|
||||
rx="2"
|
||||
/><path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
||||
</svg>
|
||||
<svg
|
||||
v-else
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2.2"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
/><path d="M2 12h20M12 2a15 15 0 0 1 0 20M12 2a15 15 0 0 0 0 20" />
|
||||
</svg>
|
||||
{{ repo.visibility === 'private' ? '비공개' : '공개' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="rh-slug">
|
||||
{{ repo.owner }} / {{ repo.id }}
|
||||
</div>
|
||||
<div class="rh-desc">
|
||||
{{ repo.desc }}
|
||||
</div>
|
||||
<div class="rh-meta">
|
||||
<span class="mi">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line
|
||||
x1="6"
|
||||
y1="3"
|
||||
x2="6"
|
||||
y2="15"
|
||||
/><circle
|
||||
cx="18"
|
||||
cy="6"
|
||||
r="3"
|
||||
/><circle
|
||||
cx="6"
|
||||
cy="18"
|
||||
r="3"
|
||||
/><path d="M18 9a9 9 0 0 1-9 9" />
|
||||
</svg>
|
||||
{{ repo.branch }}
|
||||
</span>
|
||||
<span class="mi avstack">
|
||||
<span
|
||||
v-for="m in avatars"
|
||||
:key="m.id"
|
||||
class="avatar"
|
||||
:class="m.color"
|
||||
>{{ m.initial }}</span>
|
||||
<span
|
||||
v-if="extra > 0"
|
||||
class="avatar av-more"
|
||||
>+{{ extra }}</span>
|
||||
</span>
|
||||
<span class="mi">{{ metaText }}</span>
|
||||
</div>
|
||||
<!-- 진행률 스트립 등 추가 영역 -->
|
||||
<slot name="extra" />
|
||||
</div>
|
||||
<div class="rh-actions">
|
||||
<slot name="actions">
|
||||
<RouterLink
|
||||
class="btn primary"
|
||||
:to="`/repos/${repo.id}/tasks/new`"
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2.2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M5 12h14M12 5v14" />
|
||||
</svg>
|
||||
새 업무
|
||||
</RouterLink>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.repo-head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 0.625rem;
|
||||
padding: 1.25rem 1.375rem;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
.repo-ico {
|
||||
width: 2.875rem;
|
||||
height: 2.875rem;
|
||||
border-radius: 0.625rem;
|
||||
background: var(--accent-weak);
|
||||
color: var(--accent);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.repo-ico svg {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
.rh-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.rh-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.625rem;
|
||||
}
|
||||
.rh-name {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01875rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rh-slug {
|
||||
font-size: 0.781rem;
|
||||
color: var(--text-3);
|
||||
margin-top: 0.3125rem;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
}
|
||||
.rh-desc {
|
||||
font-size: 0.844rem;
|
||||
color: var(--text-2);
|
||||
margin-top: 0.375rem;
|
||||
}
|
||||
.rh-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.9375rem;
|
||||
margin-top: 0.75rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-3);
|
||||
}
|
||||
.rh-meta .mi {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3125rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rh-meta .mi svg {
|
||||
width: 0.8125rem;
|
||||
height: 0.8125rem;
|
||||
}
|
||||
.rh-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,88 @@
|
||||
<script setup lang="ts">
|
||||
// 저장소 서브탭 — 업무/멤버/활동/설정
|
||||
import { RouterLink } from 'vue-router'
|
||||
|
||||
interface Props {
|
||||
repoId: string
|
||||
active: 'tasks' | 'members' | 'activity' | 'settings'
|
||||
taskCount: number
|
||||
memberCount: number
|
||||
}
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="tabs">
|
||||
<RouterLink
|
||||
:to="`/repos/${repoId}`"
|
||||
:class="{ active: active === 'tasks' }"
|
||||
>
|
||||
<span class="tb-label">업무</span> <span class="tb-count">{{ taskCount }}</span>
|
||||
</RouterLink>
|
||||
<RouterLink
|
||||
:to="`/repos/${repoId}/members`"
|
||||
:class="{ active: active === 'members' }"
|
||||
>
|
||||
<span class="tb-label">멤버</span> <span class="tb-count">{{ memberCount }}</span>
|
||||
</RouterLink>
|
||||
<RouterLink
|
||||
:to="`/repos/${repoId}/activity`"
|
||||
:class="{ active: active === 'activity' }"
|
||||
>
|
||||
<span class="tb-label">활동</span>
|
||||
</RouterLink>
|
||||
<RouterLink
|
||||
:to="`/repos/${repoId}/settings`"
|
||||
:class="{ active: active === 'settings' }"
|
||||
>
|
||||
<span class="tb-label">설정</span>
|
||||
</RouterLink>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 0.125rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
margin: 1.25rem 0 1.125rem;
|
||||
}
|
||||
.tabs a {
|
||||
padding: 0.625rem 0.875rem;
|
||||
font-size: 0.844rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-2);
|
||||
text-decoration: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tabs a:hover {
|
||||
color: var(--text);
|
||||
}
|
||||
.tabs a.active {
|
||||
color: var(--accent);
|
||||
border-bottom-color: var(--accent);
|
||||
}
|
||||
.tabs a .tb-count {
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-2);
|
||||
background: #f1f2f4;
|
||||
border-radius: 20px;
|
||||
padding: 0 0.4375rem;
|
||||
height: 1.0625rem;
|
||||
min-width: 1.0625rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
}
|
||||
.tabs a.active .tb-count {
|
||||
background: var(--accent-weak);
|
||||
color: var(--accent);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user