File size: 6,593 Bytes
0e13326
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
'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>
  )
}