reopt designreopt design
DocsExploreToolsPricingBuilder
시작하기
개요
시작하기
Next.js 설치
Private install
핵심 개념
아키텍처
컴포지션 패턴
접근성
키보드 패턴
스타일링
테마 시스템
고급 패턴
구축·운영
Skills
AI 연동
CLI (opt surface add)
의존 그래프
도구
Canvas 카탈로그
Theme Builder
Form Builder
템플릿
템플릿
릴리즈
릴리즈 노트
Oopt-ui
reopt designreopt design

AI 시대를 위한 디자인 시스템

  • 문서
  • 가격
  • 릴리즈 노트
  • GitHub
  • 서비스 약관
  • 개인정보처리방침

© 2026 reopt-ai. All rights reserved.

DeploymentCenter

surface

배포 관리 통합 대시보드. BranchSelect + StatusSelect + QuickActions + DeploymentTimeline + DomainTable + EnvPanel 조합.

컴포넌트 의존 관계

깊이
▼ USES (7)DeploymentCenterbranch-selectstatus-selectquick-actionsdeployment-timelinedomain-tableenv-panelloading-overlay
100%

전체 기능

배포 센터

CI/CD 대시보드

빠른 작업

배포 이력

도메인

DomainStatusSSLRedirectAdded
example.comActiveValid—2024-01-15
api.example.comActiveValidexample.com—
staging.example.comPendingPending——

환경 변수

제어 컴포넌트

배포 센터

선택: main / all

빠른 작업

배포 이력

도메인

DomainStatusSSLRedirectAdded
example.comActiveValid—2024-01-15
api.example.comActiveValidexample.com—
staging.example.comPendingPending——

환경 변수

배포 + 도메인만

배포 이력

도메인

DomainStatusSSLRedirectAdded
example.comActiveValid—2024-01-15
api.example.comActiveValidexample.com—
staging.example.comPendingPending——

환경 변수만

환경 변수

빠른 작업만

빠른 작업

빈 상태

배포 센터가 비어 있습니다

브랜치, 배포, 도메인, 또는 환경 변수 데이터를 전달하세요.

커스텀 라벨 (i18n)

Deployment History

테스트 커버리지

2026년 2월 4일

생성된 테스트 결과를 찾지 못했습니다.

DeploymentCenter 항목이 문서 메타에 연결되어 있지만 현재 생성 파일에는 없습니다.

테스트를 추가한 뒤 `bun run generate:test-results`를 실행하거나 `testDescribe` 매핑을 다시 확인하세요.

DeploymentCenter Props

Prop타입기본값설명
branchesBranchDef[]—브랜치 선택 옵션
statusOptionsSelectOption[]—상태 필터 옵션
deploymentsDeploymentStep[]—배포 이력 배열
domainsDomainDef[]—도메인 목록 배열
envGroupsEnvGroupDef[]—환경 변수 그룹 배열
quickActionsQuickActionDef[]—빠른 작업 배열
selectedBranchstring—제어 모드: 선택된 브랜치
onBranchChange(branch: string) => void—브랜치 변경 핸들러
selectedStatusstring—제어 모드: 선택된 상태
onStatusChange(status: string) => void—상태 변경 핸들러
labelsDeploymentCenterLabels—i18n 섹션 라벨
headerReactNode—상단 헤더 영역
classNamestring—최외곽 컨테이너 CSS 클래스

Surface 설치

CLI가 공식 배포 채널입니다. 필요한 Surface를 프로젝트로 복사한 뒤 직접 수정할 수 있습니다.

bash
npx @reopt-ai/opt-cli surface add deployment-center

Consumer target

복사된 파일은 components/surfaces 아래에 저장됩니다.

tsx
import { DeploymentCenter } from "@/components/surfaces/deployment-center";

Registry metadata

설명
배포 관리 통합 대시보드. BranchSelect + StatusSelect + QuickActions + DeploymentTimeline + DomainTable + EnvPanel 조합.
파일 수
1개
Registry dependencies
없음
Package dependencies
lucide-react
태그
dashboard
Install notes
  • Install additional packages: lucide-react.

포함 파일

  • deployment-center.tsx→deployment-center.tsx
Surface 소스 보기
deployment-center.tsx
"use client";

import type { ReactNode } from "react";
import { Rocket } from "lucide-react";
import { BranchSelect, StatusSelect, QuickActions, DeploymentTimeline, DomainTable, EnvPanel, OPT_TEXT_PRIMARY, OPT_TEXT_SECONDARY, SurfaceLayout } from "@reopt-ai/opt-ui";
import type { BranchDef, SelectOption, DeploymentStep, DomainDef, EnvGroupDef, QuickActionDef } from "@reopt-ai/opt-ui";

/** Localized labels for the deployment center component. */
export interface DeploymentCenterLabels {
  branch?: string;
  status?: string;
  quickActions?: string;
  deployments?: string;
  domains?: string;
  env?: string;
  emptyTitle?: string;
  emptyDescription?: string;
}

const defaultLabels: Required<DeploymentCenterLabels> = {
  branch: "브랜치",
  status: "상태",
  quickActions: "빠른 작업",
  deployments: "배포 이력",
  domains: "도메인",
  env: "환경 변수",
  emptyTitle: "배포 센터가 비어 있습니다",
  emptyDescription: "브랜치, 배포, 도메인, 또는 환경 변수 데이터를 전달하세요.",
};

/** Props for the deployment center component. */
export interface DeploymentCenterProps {
  // 선택 데이터
  branches?: BranchDef[];
  statusOptions?: SelectOption[];

  // 표시 데이터
  deployments?: DeploymentStep[];
  domains?: DomainDef[];
  envGroups?: EnvGroupDef[];
  quickActions?: QuickActionDef[];

  // 상태 관리 (제어 컴포넌트)
  selectedBranch?: string;
  onBranchChange?: (branch: string) => void;
  selectedStatus?: string;
  onStatusChange?: (status: string) => void;

  // 섹션 제목 (i18n)
  labels?: DeploymentCenterLabels;

  // 확장 슬롯
  header?: ReactNode;
  className?: string;
  loading?: boolean;
}

/** Renders the deployment center component. */
export function DeploymentCenter({
  branches,
  statusOptions,
  deployments,
  domains,
  envGroups,
  quickActions,
  selectedBranch,
  onBranchChange,
  selectedStatus,
  onStatusChange,
  labels: customLabels,
  header,
  className,
  loading = false,
}: DeploymentCenterProps) {
  const labels = { ...defaultLabels, ...customLabels };

  const hasSelectors = branches || statusOptions;
  const hasQuickActions = quickActions && quickActions.length > 0;
  const hasDeployments = deployments && deployments.length > 0;
  const hasDomains = domains && domains.length > 0;
  const hasMainContent = hasDeployments || hasDomains;
  const hasEnvGroups = envGroups && envGroups.length > 0;

  const isEmpty =
    !hasSelectors &&
    !hasQuickActions &&
    !hasDeployments &&
    !hasDomains &&
    !hasEnvGroups;

  return (
    <SurfaceLayout
      loading={loading}
      className={className}
      data-opt-id="8Q888"
      data-opt-slug="deployment-center.DeploymentCenter"
    >
      {/* 헤더 */}
      {header && <div>{header}</div>}

      {/* 선택 영역 */}
      {hasSelectors && (
        <div className="gap-group flex flex-wrap items-end">
          {branches && branches.length > 0 && (
            <BranchSelect
              branches={branches}
              value={selectedBranch}
              onChange={onBranchChange}
              label={labels.branch}
            />
          )}
          {statusOptions && statusOptions.length > 0 && (
            <StatusSelect
              options={statusOptions}
              value={selectedStatus}
              onChange={onStatusChange}
              label={labels.status}
            />
          )}
        </div>
      )}

      {/* 빠른 작업 */}
      {hasQuickActions && (
        <section aria-label={labels.quickActions}>
          <QuickActions
            actions={quickActions}
            title={labels.quickActions}
            layout="grid"
            columns={3}
          />
        </section>
      )}

      {/* 메인 콘텐츠 (2컬럼) */}
      {hasMainContent && (
        <div className="gap-section grid lg:grid-cols-2">
          {hasDeployments && (
            <section
              className="border-border rounded-xl border p-4"
              aria-label={labels.deployments}
            >
              <DeploymentTimeline
                steps={deployments}
                title={labels.deployments}
              />
            </section>
          )}
          {hasDomains && (
            <section
              className="border-border rounded-xl border p-4"
              aria-label={labels.domains}
            >
              <DomainTable domains={domains} title={labels.domains} />
            </section>
          )}
        </div>
      )}

      {/* 환경 변수 */}
      {hasEnvGroups && (
        <section
          className="border-border rounded-xl border p-4"
          aria-label={labels.env}
        >
          <h3 className={`mb-4 text-lg font-semibold ${OPT_TEXT_PRIMARY}`}>
            {labels.env}
          </h3>
          <EnvPanel groups={envGroups} />
        </section>
      )}

      {/* 빈 상태 */}
      {isEmpty && (
        <div
          role="status"
          className="flex flex-col items-center justify-center py-16 text-center"
        >
          <Rocket className="mb-4 size-10" aria-hidden />
          <h3 className={`text-lg font-medium ${OPT_TEXT_PRIMARY}`}>
            {labels.emptyTitle}
          </h3>
          <p className={`mt-1 text-sm ${OPT_TEXT_SECONDARY}`}>
            {labels.emptyDescription}
          </p>
        </div>
      )}
    </SurfaceLayout>
  );
}