feat: deploy zopu single-node production
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { cn } from "@code/ui/lib/utils";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
import type { MobileProjectView } from "./models";
|
||||
|
||||
export interface MobileProjectSelectProps {
|
||||
readonly activeCount: number;
|
||||
readonly className?: string;
|
||||
readonly onProjectSelect: (projectId: string) => void;
|
||||
readonly projects: readonly MobileProjectView[];
|
||||
readonly selectedProjectId?: string;
|
||||
}
|
||||
|
||||
export const MobileProjectSelect = ({
|
||||
activeCount,
|
||||
className,
|
||||
onProjectSelect,
|
||||
projects,
|
||||
selectedProjectId,
|
||||
}: MobileProjectSelectProps) => (
|
||||
<div
|
||||
className={cn(
|
||||
"mt-0.5 flex min-w-0 items-center gap-1.5 text-[12px] leading-4 text-[#7c7772]",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<span className="size-1.5 shrink-0 rounded-full bg-[#64ad1f]" />
|
||||
<label className="relative min-w-0">
|
||||
<span className="sr-only">Connected project</span>
|
||||
<select
|
||||
aria-label="Connected project"
|
||||
className="max-w-[132px] cursor-pointer appearance-none truncate bg-transparent pr-4 font-medium text-[#5d5955] outline-none focus-visible:ring-2 focus-visible:ring-[#315dc0]"
|
||||
onChange={(event) => onProjectSelect(event.currentTarget.value)}
|
||||
value={selectedProjectId ?? ""}
|
||||
>
|
||||
{projects.length === 0 ? (
|
||||
<option value="">No connected project</option>
|
||||
) : null}
|
||||
{projects.map((project) => (
|
||||
<option key={project.id} value={project.id}>
|
||||
{project.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDown
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute top-1/2 right-0 size-3 -translate-y-1/2"
|
||||
/>
|
||||
</label>
|
||||
<span aria-hidden="true">·</span>
|
||||
<span className="shrink-0 tabular-nums">{activeCount} active</span>
|
||||
</div>
|
||||
);
|
||||
@@ -10,8 +10,10 @@ import {
|
||||
} from "lucide-react";
|
||||
import type { FormEvent, MouseEvent } from "react";
|
||||
|
||||
import { MobileProjectSelect } from "./mobile-project-select";
|
||||
import { MobileSettingsPanel } from "./mobile-settings-panel";
|
||||
import type {
|
||||
MobileProjectView,
|
||||
MobileWorkspaceView,
|
||||
MobileWorkUnitTone,
|
||||
MobileWorkUnitView,
|
||||
@@ -41,12 +43,18 @@ const dateLabel = new Intl.DateTimeFormat("en", {
|
||||
interface WorkStackHeaderProps {
|
||||
readonly activeCount: number;
|
||||
readonly onOpenSettings?: () => void;
|
||||
readonly onProjectSelect: (projectId: string) => void;
|
||||
readonly projects: readonly MobileProjectView[];
|
||||
readonly selectedProjectId?: string;
|
||||
readonly userInitials: string;
|
||||
}
|
||||
|
||||
const WorkStackHeader = ({
|
||||
activeCount,
|
||||
onOpenSettings,
|
||||
onProjectSelect,
|
||||
projects,
|
||||
selectedProjectId,
|
||||
userInitials,
|
||||
}: WorkStackHeaderProps) => (
|
||||
<header className="flex h-[96px] shrink-0 items-center bg-white px-4">
|
||||
@@ -57,10 +65,12 @@ const WorkStackHeader = ({
|
||||
<h1 className="text-[20px] leading-6 font-semibold tracking-[-0.03em] text-[#0b0b0a]">
|
||||
Zopu
|
||||
</h1>
|
||||
<p className="mt-0.5 flex items-center gap-2 text-[13px] leading-4 text-[#7c7772]">
|
||||
<span className="size-1.5 rounded-full bg-[#64ad1f]" />
|
||||
{activeCount} active work units
|
||||
</p>
|
||||
<MobileProjectSelect
|
||||
activeCount={activeCount}
|
||||
onProjectSelect={onProjectSelect}
|
||||
projects={projects}
|
||||
selectedProjectId={selectedProjectId}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
aria-label="Open settings"
|
||||
@@ -291,6 +301,7 @@ export interface MobileWorkStackScreenProps {
|
||||
readonly onComposerChange: (value: string) => void;
|
||||
readonly onComposerSubmit: (event: FormEvent<HTMLFormElement>) => void;
|
||||
readonly onOpenUnit: (workUnitId: string) => void;
|
||||
readonly onProjectSelect: (projectId: string) => void;
|
||||
readonly onRestoreChecked: () => void;
|
||||
readonly onSettingsClose: () => void;
|
||||
readonly onSettingsOpen: () => void;
|
||||
@@ -314,6 +325,7 @@ export const MobileWorkStackScreen = ({
|
||||
onComposerChange,
|
||||
onComposerSubmit,
|
||||
onOpenUnit,
|
||||
onProjectSelect,
|
||||
onRestoreChecked,
|
||||
onSettingsClose,
|
||||
onSettingsOpen,
|
||||
@@ -339,6 +351,9 @@ export const MobileWorkStackScreen = ({
|
||||
<WorkStackHeader
|
||||
activeCount={data.activeCount}
|
||||
onOpenSettings={onSettingsOpen}
|
||||
onProjectSelect={onProjectSelect}
|
||||
projects={data.projects}
|
||||
selectedProjectId={data.selectedProjectId}
|
||||
userInitials={userInitials}
|
||||
/>
|
||||
<main className="relative min-h-0 flex-1 overflow-hidden bg-[#f7f8f5] px-5 pt-[26px]">
|
||||
|
||||
Reference in New Issue
Block a user