Racks can now be marked for decommission from the DC view. The rack leaves production immediately (freeing slot and power), enters the pipeline as a timed decommission order, and is removed when complete. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Plus, Server, MapPin, Zap, HardDrive, Wrench, ChevronDown, ChevronUp, Thermometer, Shield } from 'lucide-react';
|
||||
import { Plus, Server, MapPin, Zap, HardDrive, Wrench, ChevronDown, ChevronUp, Thermometer, Shield, X } from 'lucide-react';
|
||||
import { useGameStore } from '@/store';
|
||||
import {
|
||||
formatMoney, formatNumber, formatPercent,
|
||||
@@ -16,6 +16,7 @@ const STAGE_LABELS: Record<PipelineStage, string> = {
|
||||
installation: 'Installation',
|
||||
testing: 'Testing',
|
||||
repair: 'Repair',
|
||||
decommission: 'Decom',
|
||||
};
|
||||
|
||||
const STAGE_COLORS: Record<PipelineStage, string> = {
|
||||
@@ -25,6 +26,7 @@ const STAGE_COLORS: Record<PipelineStage, string> = {
|
||||
installation: 'bg-violet-500',
|
||||
testing: 'bg-amber-500',
|
||||
repair: 'bg-danger',
|
||||
decommission: 'bg-surface-500',
|
||||
};
|
||||
|
||||
function PipelineKanban() {
|
||||
@@ -32,7 +34,7 @@ function PipelineKanban() {
|
||||
|
||||
if (pipeline.length === 0) return null;
|
||||
|
||||
const stages: PipelineStage[] = ['ordered', 'manufacturing', 'receiving', 'installation', 'testing', 'repair'];
|
||||
const stages: PipelineStage[] = ['ordered', 'manufacturing', 'receiving', 'installation', 'testing', 'repair', 'decommission'];
|
||||
const grouped = stages.map(stage => ({
|
||||
stage,
|
||||
orders: pipeline.filter(o => o.stage === stage),
|
||||
@@ -41,7 +43,7 @@ function PipelineKanban() {
|
||||
return (
|
||||
<div className="bg-surface-900 border border-surface-700 rounded-xl p-4">
|
||||
<h3 className="text-sm font-semibold text-surface-300 uppercase mb-3">Rack Pipeline</h3>
|
||||
<div className="grid grid-cols-6 gap-2">
|
||||
<div className="grid grid-cols-7 gap-2">
|
||||
{grouped.map(({ stage, orders }) => (
|
||||
<div key={stage}>
|
||||
<div className="text-[10px] text-surface-400 uppercase mb-1.5 text-center">
|
||||
@@ -108,14 +110,16 @@ function DataCenterCard({ dcId }: { dcId: string }) {
|
||||
const era = useGameStore((s) => s.meta.currentEra);
|
||||
const completedResearch = useGameStore((s) => s.research.completedResearch);
|
||||
const orderRack = useGameStore((s) => s.orderRack);
|
||||
const decommissionRack = useGameStore((s) => s.decommissionRack);
|
||||
const upgradeDataCenter = useGameStore((s) => s.upgradeDataCenter);
|
||||
const [expanded, setExpanded] = useState(true);
|
||||
|
||||
const tierConfig = DC_TIER_CONFIGS[dc.tier];
|
||||
const currentEraIdx = ERA_ORDER.indexOf(era);
|
||||
const liveUsedSlots = dc.racks.length + pipelineForDc.length;
|
||||
const activePipeline = pipelineForDc.filter(o => o.stage !== 'decommission');
|
||||
const liveUsedSlots = dc.racks.length + activePipeline.length;
|
||||
const liveUsedPower = dc.racks.reduce((s, r) => s + RACK_SKU_CONFIGS[r.skuId].powerDrawKW, 0)
|
||||
+ pipelineForDc.reduce((s, o) => s + RACK_SKU_CONFIGS[o.skuId].powerDrawKW, 0);
|
||||
+ activePipeline.reduce((s, o) => s + RACK_SKU_CONFIGS[o.skuId].powerDrawKW, 0);
|
||||
|
||||
const availableSkus = Object.values(RACK_SKU_CONFIGS).filter(sku => {
|
||||
if (ERA_ORDER.indexOf(sku.era) > currentEraIdx) return false;
|
||||
@@ -180,11 +184,18 @@ function DataCenterCard({ dcId }: { dcId: string }) {
|
||||
{dc.racks.map(rack => {
|
||||
const sku = RACK_SKU_CONFIGS[rack.skuId];
|
||||
return (
|
||||
<div key={rack.id} className={`text-[11px] rounded p-1.5 border ${
|
||||
<div key={rack.id} className={`text-[11px] rounded p-1.5 border relative group ${
|
||||
rack.isHealthy
|
||||
? 'bg-surface-800 border-surface-600'
|
||||
: 'bg-danger/10 border-danger/30'
|
||||
}`}>
|
||||
<button
|
||||
onClick={() => decommissionRack(dc.id, rack.id)}
|
||||
className="absolute top-0.5 right-0.5 p-0.5 rounded opacity-0 group-hover:opacity-100 hover:bg-danger/20 text-surface-400 hover:text-danger transition-all"
|
||||
title="Decommission rack"
|
||||
>
|
||||
<X size={10} />
|
||||
</button>
|
||||
<div className="font-medium truncate">{sku.name}</div>
|
||||
<div className="text-surface-400">{formatNumber(sku.flopsPerRack)} FLOPS</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user