Runs / loan-contract Batch Runs from different design-system versions should not be compared.
The page A screenshot in each theme, as the benchmark took it.
page.tsx As the agent left it; marked lines broke a rule.
Violations None. The run followed every rule that was checked.
Steps One row per model call, with the tools it asked for. An agent that reads the guidelines before writing shows it here; what a checker or submit_view answered is under its call.
Step Tools Tokens in Tokens out Cost 0 get_guidelines 801 101 $0.0027 1 list_files, list_components, list_tokens 1,511 75 $0.0040 2 read_file, get_component, get_component, get_component 1,958 178 $0.0062
e02ef3974528
Output cap The provider's default 4 CardBody,
5 CardDescription,
6 CardHeader,
7 CardTitle,
8 Table,
9 TableBody,
10 TableCell,
11 TableHead,
12 TableHeader,
13 TableRow,
14 } from "@vektos/ds";
15 import { css } from "styled-system/css";
16 import data from "./fixture.json";
17
18 type BadgeTone = "neutral" | "success" | "warning" | "danger";
19
20 const currencyFormatter = new Intl.NumberFormat("en-IE", {
21 style: "currency",
22 currency: data.contract.currency,
23 minimumFractionDigits: 2,
24 maximumFractionDigits: 2,
25 });
26
27 const percentFormatter = new Intl.NumberFormat("en-IE", {
28 style: "percent",
29 minimumFractionDigits: 2,
30 maximumFractionDigits: 2,
31 });
32
33 const longDateFormatter = new Intl.DateTimeFormat("en-GB", {
34 day: "2-digit",
35 month: "long",
36 year: "numeric",
37 timeZone: "UTC",
38 });
39
40 const shortDateFormatter = new Intl.DateTimeFormat("en-GB", {
41 day: "2-digit",
42 month: "short",
43 year: "numeric",
44 timeZone: "UTC",
45 });
46
47 function asUtcDate(value: string) {
48 return new Date(`${value}T00:00:00Z`);
49 }
50
51 function statusLabel(status: string) {
52 return status.charAt(0).toUpperCase() + status.slice(1);
53 }
54
55 function statusTone(status: string): BadgeTone {
56 switch (status) {
57 case "active":
58 case "paid":
59 return "success";
60 case "due":
61 return "warning";
62 default:
63 return "neutral";
64 }
65 }
66
67 const page = css({
68 bg: "bg.canvas",
69 color: "fg.default",
70 px: "4",
71 py: "6",
72 });
73
74 const content = css({
75 width: "full",
76 maxWidth: "full",
77 mx: "auto",
78 display: "flex",
79 flexDirection: "column",
80 gap: "6",
81 });
82
83 const pageHeader = css({
84 display: "flex",
85 flexDirection: "column",
86 gap: "2",
87 });
88
89 const eyebrow = css({
90 color: "fg.muted",
91 fontSize: "sm",
92 fontWeight: "medium",
93 });
94
95 const titleRow = css({
96 display: "flex",
97 alignItems: "center",
98 flexWrap: "wrap",
99 gap: "3",
100 });
101
102 const pageTitle = css({
103 fontSize: "lg",
104 fontWeight: "semibold",
105 lineHeight: "tight",
106 });
107
108 const contractMeta = css({
109 color: "fg.muted",
110 fontSize: "sm",
111 });
112
113 const contractNumber = css({
114 color: "fg.default",
115 fontWeight: "medium",
116 });
117
118 const sectionTitle = css({
119 fontSize: "md",
120 fontWeight: "semibold",
121 lineHeight: "tight",
122 });
123
124 const keyTermsHeader = css({
125 display: "flex",
126 flexDirection: "row",
127 flexWrap: "wrap",
128 alignItems: "center",
129 justifyContent: "space-between",
130 gap: "4",
131 });
132
133 const outstanding = css({
134 display: "flex",
135 flexDirection: "column",
136 gap: "1",
137 });
138
139 const outstandingLabel = css({
140 color: "fg.muted",
141 fontSize: "sm",
142 });
143
144 const outstandingValue = css({
145 fontSize: "lg",
146 fontWeight: "semibold",
147 lineHeight: "tight",
148 });
149
150 const termsGrid = css({
151 display: "grid",
152 gridTemplateColumns: "repeat(auto-fit, minmax(14rem, 1fr))",
153 gap: "4",
154 });
155
156 const term = css({
157 bg: "bg.subtle",
158 rounded: "md",
159 p: "4",
160 display: "flex",
161 flexDirection: "column",
162 gap: "2",
163 });
164
165 const termLabel = css({
166 color: "fg.muted",
167 fontSize: "sm",
168 });
169
170 const termValue = css({
171 color: "fg.default",
172 fontSize: "md",
173 fontWeight: "semibold",
174 lineHeight: "tight",
175 });
176
177 const tableScroll = css({
178 width: "full",
179 overflowX: "auto",
180 });
181
182 const scheduleTable = css({
183 whiteSpace: "nowrap",
184 });
185
186 const paymentCell = css({
187 fontWeight: "semibold",
188 });
189
190 const documentList = css({
191 display: "flex",
192 flexDirection: "column",
193 gap: "3",
194 listStyleType: "none",
195 m: "0",
196 p: "0",
197 });
198
199 const documentItem = css({
200 display: "flex",
201 alignItems: "center",
202 justifyContent: "space-between",
203 flexWrap: "wrap",
204 gap: "4",
205 bg: "bg.subtle",
206 rounded: "md",
207 p: "4",
208 });
209
210 const documentNameGroup = css({
211 display: "flex",
212 alignItems: "center",
213 gap: "3",
214 });
215
216 const signedIcon = css({
217 width: "8",
218 height: "8",
219 rounded: "full",
220 bg: "success.subtle",
221 color: "success.text",
222 display: "flex",
223 alignItems: "center",
224 justifyContent: "center",
225 flexShrink: 0,
226 fontSize: "sm",
227 fontWeight: "semibold",
228 });
229
230 const documentName = css({
231 fontSize: "sm",
232 fontWeight: "medium",
233 });
234
235 const signedDate = css({
236 color: "fg.muted",
237 fontSize: "sm",
238 whiteSpace: "nowrap",
239 });
240
241 export default function LoanContractPage() {
242 const { contract } = data;
243 const terms: Array<{ label: string; value: string; dateTime?: string }> = [
244 { label: "Amount borrowed", value: currencyFormatter.format(contract.principal) },
245 { label: "Nominal interest rate", value: percentFormatter.format(contract.nominalRate) },
246 { label: "APR", value: percentFormatter.format(contract.apr) },
247 { label: "Term", value: `${contract.termMonths} months` },
248 { label: "Monthly payment", value: currencyFormatter.format(contract.monthlyPayment) },
249 {
250 label: "Start date",
251 value: longDateFormatter.format(asUtcDate(contract.startDate)),
252 dateTime: contract.startDate,
253 },
254 ];
255
256 return (
257 <div className={`vektos ${page}`}>
258 <main className={content} aria-labelledby="contract-title">
259 <header className={pageHeader}>
260 <p className={eyebrow}>Loan contract</p>
261 <div className={titleRow}>
262 <h1 id="contract-title" className={pageTitle}>
263 {contract.product}
264 </h1>
265 <Badge tone={statusTone(contract.status)}>{statusLabel(contract.status)}</Badge>
266 </div>
267 <p className={contractMeta}>
268 Contract <span className={contractNumber}>{contract.number}</span>
269 <span aria-hidden="true"> · </span>
270 Borrower {contract.borrower}
271 </p>
272 </header>
273
274 <Card>
275 <CardHeader className={keyTermsHeader}>
276 <div>
277 <CardTitle asChild>
278 <h2 className={sectionTitle}>Key terms</h2>
279 </CardTitle>
280 <CardDescription>The agreed terms for this personal loan.</CardDescription>
281 </div>
282 <div className={outstanding}>
283 <span className={outstandingLabel}>Still owed</span>
284 <span className={outstandingValue}>
285 {currencyFormatter.format(contract.outstanding)}
286 </span>
287 </div>
288 </CardHeader>
289 <CardBody>
290 <dl className={termsGrid}>
291 {terms.map((item) => (
292 <div className={term} key={item.label}>
293 <dt className={termLabel}>{item.label}</dt>
294 <dd className={termValue}>
295 {item.dateTime ? (
296 <time dateTime={item.dateTime}>{item.value}</time>
297 ) : (
298 item.value
299 )}
300 </dd>
301 </div>
302 ))}
303 </dl>
304 </CardBody>
305 </Card>
306
307 <Card>
308 <CardHeader>
309 <CardTitle asChild>
310 <h2 className={sectionTitle}>Repayment schedule</h2>
311 </CardTitle>
312 <CardDescription>
313 First {data.schedule.length} of {contract.termMonths} instalments. All amounts in{" "}
314 {contract.currency}.
315 </CardDescription>
316 </CardHeader>
317 <div className={tableScroll}>
318 <Table
319 aria-label={`Repayment schedule for contract ${contract.number}`}
320 className={scheduleTable}
321 >
322 <TableHead>
323 <TableRow>
324 <TableHeader numeric>Instalment</TableHeader>
325 <TableHeader>Due date</TableHeader>
326 <TableHeader numeric>Payment</TableHeader>
327 <TableHeader numeric>Principal</TableHeader>
328 <TableHeader numeric>Interest</TableHeader>
329 <TableHeader numeric>Balance after payment</TableHeader>
330 <TableHeader>Status</TableHeader>
331 </TableRow>
332 </TableHead>
333 <TableBody>
334 {data.schedule.map((instalment) => (
335 <TableRow key={instalment.number}>
336 <TableCell numeric>{instalment.number}</TableCell>
337 <TableCell>
338 <time dateTime={instalment.dueDate}>
339 {shortDateFormatter.format(asUtcDate(instalment.dueDate))}
340 </time>
341 </TableCell>
342 <TableCell numeric className={paymentCell}>
343 {currencyFormatter.format(instalment.payment)}
344 </TableCell>
345 <TableCell numeric>{currencyFormatter.format(instalment.principal)}</TableCell>
346 <TableCell numeric>{currencyFormatter.format(instalment.interest)}</TableCell>
347 <TableCell numeric>{currencyFormatter.format(instalment.remaining)}</TableCell>
348 <TableCell>
349 <Badge tone={statusTone(instalment.status)}>
350 {statusLabel(instalment.status)}
351 </Badge>
352 </TableCell>
353 </TableRow>
354 ))}
355 </TableBody>
356 </Table>
357 </div>
358 </Card>
359
360 <Card>
361 <CardHeader>
362 <CardTitle asChild>
363 <h2 className={sectionTitle}>Signed documents</h2>
364 </CardTitle>
365 <CardDescription>
366 {data.documents.length} documents signed for this contract.
367 </CardDescription>
368 </CardHeader>
369 <CardBody>
370 <ul className={documentList}>
371 {data.documents.map((document) => (
372 <li className={documentItem} key={document.name}>
373 <div className={documentNameGroup}>
374 <span className={signedIcon} aria-hidden="true">
375 ✓
376 </span>
377 <span className={documentName}>{document.name}</span>
378 </div>
379 <span className={signedDate}>
380 Signed{" "}
381 <time dateTime={document.signedAt}>
382 {longDateFormatter.format(asUtcDate(document.signedAt))}
383 </time>
384 </span>
385 </li>
386 ))}
387 </ul>
388 </CardBody>
389 </Card>
390 </main>
391 </div>
392 );
393 }
394
4 check_code 8,809 2,627 $0.0453
5 write_file 2,850 4,089 $0.0498
6 read_file 4,162 166 $0.0137
7 check_code 2,652 2,550 $0.0354