ruben de la fuente
feat: initial deployment to HuggingFace Spaces
0e13326
'use client'
import { useState } from 'react'
import { MetricsInput } from '@/lib/types'
interface MetricsFormProps {
onSubmit: (metrics: MetricsInput) => void
initialValues?: MetricsInput
}
export const defaultMetrics: MetricsInput = {
deploymentFrequency: 'weekly',
leadTimeDays: 0,
changeFailureRate: 0,
mttrHours: 0,
pipelineDurationMinutes: 0,
prReviewTimeHours: 0,
engineerCount: 1,
serviceCount: 1,
}
export default function MetricsForm({ onSubmit, initialValues }: MetricsFormProps) {
const [metrics, setMetrics] = useState<MetricsInput>(initialValues ?? defaultMetrics)
function handleSubmit(e: React.FormEvent) {
e.preventDefault()
onSubmit(metrics)
}
function setField<K extends keyof MetricsInput>(key: K, value: MetricsInput[K]) {
setMetrics((prev) => ({ ...prev, [key]: value }))
}
return (
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="deploymentFrequency" className="block text-sm font-medium text-gray-700 mb-1">
Deployment Frequency
</label>
<select
id="deploymentFrequency"
value={metrics.deploymentFrequency}
onChange={(e) =>
setField('deploymentFrequency', e.target.value as MetricsInput['deploymentFrequency'])
}
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
>
<option value="multiple_per_day">Multiple times per day</option>
<option value="daily">Once per day</option>
<option value="weekly">Once per week</option>
<option value="monthly">Once per month</option>
<option value="less_than_monthly">Less than once per month</option>
</select>
</div>
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label htmlFor="leadTimeDays" className="block text-sm font-medium text-gray-700 mb-1">
Lead Time (days)
</label>
<input
id="leadTimeDays"
type="number"
min={0}
step={0.5}
value={metrics.leadTimeDays}
onChange={(e) => setField('leadTimeDays', parseFloat(e.target.value) || 0)}
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
<div>
<label htmlFor="changeFailureRate" className="block text-sm font-medium text-gray-700 mb-1">
Change Failure Rate (%)
</label>
<input
id="changeFailureRate"
type="number"
min={0}
max={100}
step={1}
value={metrics.changeFailureRate}
onChange={(e) => setField('changeFailureRate', parseFloat(e.target.value) || 0)}
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
<div>
<label htmlFor="mttrHours" className="block text-sm font-medium text-gray-700 mb-1">
MTTR (hours)
</label>
<input
id="mttrHours"
type="number"
min={0}
step={0.5}
value={metrics.mttrHours}
onChange={(e) => setField('mttrHours', parseFloat(e.target.value) || 0)}
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
<div>
<label htmlFor="pipelineDurationMinutes" className="block text-sm font-medium text-gray-700 mb-1">
Pipeline Duration (minutes)
</label>
<input
id="pipelineDurationMinutes"
type="number"
min={0}
value={metrics.pipelineDurationMinutes}
onChange={(e) => setField('pipelineDurationMinutes', parseFloat(e.target.value) || 0)}
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
<div>
<label htmlFor="prReviewTimeHours" className="block text-sm font-medium text-gray-700 mb-1">
PR Review Time (hours)
</label>
<input
id="prReviewTimeHours"
type="number"
min={0}
step={0.5}
value={metrics.prReviewTimeHours}
onChange={(e) => setField('prReviewTimeHours', parseFloat(e.target.value) || 0)}
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
<div>
<label htmlFor="engineerCount" className="block text-sm font-medium text-gray-700 mb-1">
Engineer Count
</label>
<input
id="engineerCount"
type="number"
min={1}
step={1}
value={metrics.engineerCount}
onChange={(e) => setField('engineerCount', parseInt(e.target.value) || 1)}
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
<div>
<label htmlFor="serviceCount" className="block text-sm font-medium text-gray-700 mb-1">
Service Count
</label>
<input
id="serviceCount"
type="number"
min={1}
step={1}
value={metrics.serviceCount}
onChange={(e) => setField('serviceCount', parseInt(e.target.value) || 1)}
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
</div>
<div className="pt-2">
<button
type="submit"
className="w-full rounded-md bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
>
Next: Team Context
</button>
</div>
</form>
)
}