@rezti/dsh-rez-suite 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh.md +2 -2
- package/cordis.patch.yml +3 -50
- package/lib/client.d.ts +19 -152
- package/lib/client.js +156 -307
- package/lib/index.js +1 -1
- package/lib/style.css +82 -111
- package/package.json +10 -8
- package/src/client/index.ts +33 -21
- package/src/client/locales.ts +4 -0
- package/src/client/panel/AuditTab.tsx +6 -6
- package/src/client/panel/panel.module.css +89 -118
- package/src/client/settings-card.tsx +68 -0
- package/src/index.ts +4 -4
- package/src/client/mount.tsx +0 -97
- package/src/client/panel/RezPanel.tsx +0 -53
- package/src/client/panel/controller.ts +0 -42
- package/src/client/sidebar-entry.ts +0 -80
package/lib/style.css
CHANGED
|
@@ -1,110 +1,83 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
.WRGRRW_shell {
|
|
2
|
+
flex-direction: column;
|
|
3
|
+
gap: 12px;
|
|
4
|
+
min-width: 0;
|
|
5
|
+
display: flex;
|
|
3
6
|
}
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
background: var(--dsw-alias-bg-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
.WRGRRW_card {
|
|
9
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
10
|
+
background: var(--dsw-alias-bg-layer-3);
|
|
11
|
+
border-radius: 12px;
|
|
12
|
+
list-style: none;
|
|
13
|
+
transition: border-color .16s, background .16s;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
.WRGRRW_card:hover {
|
|
17
|
+
border-color: var(--dsw-alias-label-dimmed);
|
|
15
18
|
}
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
.WRGRRW_cardOpen {
|
|
21
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
22
|
+
border-color: var(--dsw-alias-label-dimmed);
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
.
|
|
25
|
+
.WRGRRW_header {
|
|
26
|
+
appearance: none;
|
|
22
27
|
width: 100%;
|
|
23
|
-
|
|
24
|
-
color:
|
|
28
|
+
font: inherit;
|
|
29
|
+
color: inherit;
|
|
30
|
+
text-align: left;
|
|
25
31
|
cursor: pointer;
|
|
26
|
-
white-space: nowrap;
|
|
27
32
|
background: none;
|
|
28
|
-
border:
|
|
29
|
-
border-radius:
|
|
33
|
+
border: 0;
|
|
34
|
+
border-radius: 12px;
|
|
30
35
|
align-items: center;
|
|
31
|
-
gap:
|
|
32
|
-
padding:
|
|
33
|
-
font-size: 13px;
|
|
36
|
+
gap: 12px;
|
|
37
|
+
padding: 14px 16px;
|
|
34
38
|
display: flex;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.WRGRRW_entryIcon {
|
|
43
|
-
flex: none;
|
|
44
|
-
justify-content: center;
|
|
45
|
-
align-items: center;
|
|
46
|
-
display: inline-flex;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.WRGRRW_entryLabel {
|
|
50
|
-
text-overflow: ellipsis;
|
|
51
|
-
overflow: hidden;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
[data-dsh-frame][data-sidebar-collapsed] .WRGRRW_entry {
|
|
55
|
-
justify-content: center;
|
|
56
|
-
width: 100%;
|
|
57
|
-
padding: 0;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
[data-dsh-frame][data-sidebar-collapsed] .WRGRRW_entryLabel {
|
|
61
|
-
display: none;
|
|
41
|
+
.WRGRRW_header:focus-visible {
|
|
42
|
+
outline: 2px solid var(--dsw-alias-brand-primary);
|
|
43
|
+
outline-offset: -2px;
|
|
62
44
|
}
|
|
63
45
|
|
|
64
|
-
.
|
|
65
|
-
|
|
46
|
+
.WRGRRW_headText {
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
flex: 1;
|
|
49
|
+
gap: 4px;
|
|
50
|
+
min-width: 0;
|
|
51
|
+
display: flex;
|
|
66
52
|
}
|
|
67
53
|
|
|
68
|
-
.
|
|
69
|
-
background: var(--dsw-alias-bg-base);
|
|
70
|
-
min-width: 0;
|
|
71
|
-
height: 100%;
|
|
72
|
-
min-height: 0;
|
|
54
|
+
.WRGRRW_name {
|
|
73
55
|
color: var(--dsw-alias-label-primary);
|
|
74
|
-
font-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
padding: 14px 16px 16px;
|
|
78
|
-
display: flex;
|
|
56
|
+
font-size: 15px;
|
|
57
|
+
font-weight: 600;
|
|
58
|
+
line-height: 1.4;
|
|
79
59
|
}
|
|
80
60
|
|
|
81
|
-
.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
display: flex;
|
|
61
|
+
.WRGRRW_description {
|
|
62
|
+
color: var(--dsw-alias-label-tertiary);
|
|
63
|
+
font-size: 13px;
|
|
64
|
+
line-height: 1.5;
|
|
86
65
|
}
|
|
87
66
|
|
|
88
|
-
.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
font-weight: 700;
|
|
67
|
+
.WRGRRW_chevron {
|
|
68
|
+
color: var(--dsw-alias-label-tertiary);
|
|
69
|
+
flex: none;
|
|
70
|
+
transition: transform .16s;
|
|
93
71
|
}
|
|
94
72
|
|
|
95
|
-
.
|
|
96
|
-
|
|
97
|
-
cursor: pointer;
|
|
98
|
-
background: none;
|
|
99
|
-
border: none;
|
|
100
|
-
border-radius: 6px;
|
|
101
|
-
padding: 4px 8px;
|
|
102
|
-
font-size: 14px;
|
|
73
|
+
.WRGRRW_chevronOpen {
|
|
74
|
+
transform: rotate(180deg);
|
|
103
75
|
}
|
|
104
76
|
|
|
105
|
-
.
|
|
106
|
-
|
|
107
|
-
|
|
77
|
+
.WRGRRW_body {
|
|
78
|
+
border-top: 1px solid var(--dsw-alias-border-l2);
|
|
79
|
+
margin: 0 16px 12px;
|
|
80
|
+
padding-top: 8px;
|
|
108
81
|
}
|
|
109
82
|
|
|
110
83
|
.WRGRRW_tabBar {
|
|
@@ -136,21 +109,12 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
136
109
|
font-weight: 600;
|
|
137
110
|
}
|
|
138
111
|
|
|
139
|
-
.WRGRRW_panelContent {
|
|
140
|
-
flex-direction: column;
|
|
141
|
-
flex: 1;
|
|
142
|
-
min-height: 0;
|
|
143
|
-
display: flex;
|
|
144
|
-
overflow: hidden;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
112
|
.WRGRRW_tabBody {
|
|
148
113
|
flex-direction: column;
|
|
149
|
-
flex: 1;
|
|
150
114
|
gap: 12px;
|
|
151
|
-
min-
|
|
115
|
+
min-width: 0;
|
|
116
|
+
padding: 12px 0 4px;
|
|
152
117
|
display: flex;
|
|
153
|
-
overflow-y: auto;
|
|
154
118
|
}
|
|
155
119
|
|
|
156
120
|
.WRGRRW_section {
|
|
@@ -164,16 +128,17 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
164
128
|
}
|
|
165
129
|
|
|
166
130
|
.WRGRRW_sectionTitle {
|
|
131
|
+
color: var(--dsw-alias-label-primary);
|
|
167
132
|
margin: 0;
|
|
168
133
|
font-size: 13px;
|
|
169
134
|
font-weight: 600;
|
|
170
135
|
}
|
|
171
136
|
|
|
172
137
|
.WRGRRW_field {
|
|
173
|
-
|
|
174
|
-
align-items:
|
|
175
|
-
gap:
|
|
176
|
-
display:
|
|
138
|
+
flex-direction: column;
|
|
139
|
+
align-items: stretch;
|
|
140
|
+
gap: 4px;
|
|
141
|
+
display: flex;
|
|
177
142
|
}
|
|
178
143
|
|
|
179
144
|
.WRGRRW_label {
|
|
@@ -183,7 +148,7 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
183
148
|
|
|
184
149
|
.WRGRRW_input, .WRGRRW_select {
|
|
185
150
|
color: var(--dsw-alias-label-primary);
|
|
186
|
-
background: var(--dsw-specific-input-major);
|
|
151
|
+
background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));
|
|
187
152
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
188
153
|
border-radius: 8px;
|
|
189
154
|
outline: none;
|
|
@@ -207,7 +172,7 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
207
172
|
|
|
208
173
|
.WRGRRW_button {
|
|
209
174
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
210
|
-
background: var(--dsw-specific-input-major);
|
|
175
|
+
background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));
|
|
211
176
|
color: var(--dsw-alias-label-primary);
|
|
212
177
|
cursor: pointer;
|
|
213
178
|
border-radius: 8px;
|
|
@@ -215,23 +180,19 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
215
180
|
font-size: 13px;
|
|
216
181
|
}
|
|
217
182
|
|
|
218
|
-
.WRGRRW_button:hover {
|
|
183
|
+
.WRGRRW_button:hover:not(:disabled) {
|
|
219
184
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
220
185
|
}
|
|
221
186
|
|
|
222
|
-
.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
width: 240px;
|
|
226
|
-
height: 240px;
|
|
227
|
-
margin: 8px 0;
|
|
228
|
-
display: block;
|
|
187
|
+
.WRGRRW_button:disabled {
|
|
188
|
+
opacity: .4;
|
|
189
|
+
cursor: default;
|
|
229
190
|
}
|
|
230
191
|
|
|
231
192
|
.WRGRRW_primaryButton {
|
|
232
|
-
background: var(--dsw-alias-
|
|
233
|
-
border-color: var(--dsw-alias-
|
|
234
|
-
color:
|
|
193
|
+
background: var(--dsw-alias-label-primary);
|
|
194
|
+
border-color: var(--dsw-alias-label-primary);
|
|
195
|
+
color: var(--dsw-alias-bg-layer-3);
|
|
235
196
|
}
|
|
236
197
|
|
|
237
198
|
.WRGRRW_dangerButton {
|
|
@@ -240,9 +201,20 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
240
201
|
color: #fff;
|
|
241
202
|
}
|
|
242
203
|
|
|
204
|
+
.WRGRRW_qr {
|
|
205
|
+
background: #fff;
|
|
206
|
+
border-radius: 8px;
|
|
207
|
+
width: 200px;
|
|
208
|
+
height: 200px;
|
|
209
|
+
margin: 8px 0;
|
|
210
|
+
display: block;
|
|
211
|
+
}
|
|
212
|
+
|
|
243
213
|
.WRGRRW_message {
|
|
244
214
|
color: var(--dsw-alias-label-secondary);
|
|
215
|
+
margin: 0;
|
|
245
216
|
font-size: 12.5px;
|
|
217
|
+
line-height: 1.5;
|
|
246
218
|
}
|
|
247
219
|
|
|
248
220
|
.WRGRRW_error {
|
|
@@ -252,8 +224,6 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
252
224
|
.WRGRRW_tableWrap {
|
|
253
225
|
border: 1px solid var(--dsw-alias-border-l1);
|
|
254
226
|
border-radius: 10px;
|
|
255
|
-
flex: 1;
|
|
256
|
-
min-height: 0;
|
|
257
227
|
overflow: auto;
|
|
258
228
|
}
|
|
259
229
|
|
|
@@ -296,12 +266,12 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
296
266
|
}
|
|
297
267
|
|
|
298
268
|
.WRGRRW_cards {
|
|
299
|
-
grid-template-columns: repeat(auto-fill, minmax(
|
|
269
|
+
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
|
300
270
|
gap: 8px;
|
|
301
271
|
display: grid;
|
|
302
272
|
}
|
|
303
273
|
|
|
304
|
-
.
|
|
274
|
+
.WRGRRW_stat {
|
|
305
275
|
border: 1px solid var(--dsw-alias-border-l1);
|
|
306
276
|
border-radius: 10px;
|
|
307
277
|
padding: 10px;
|
|
@@ -313,6 +283,7 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
|
|
|
313
283
|
}
|
|
314
284
|
|
|
315
285
|
.WRGRRW_cardValue {
|
|
286
|
+
color: var(--dsw-alias-label-primary);
|
|
316
287
|
font-size: 15px;
|
|
317
288
|
font-weight: 600;
|
|
318
289
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rezti/dsh-rez-suite",
|
|
3
3
|
"description": "ReZ-TI employee plugin for DeepSeek Harness: one install enables company MCP (Odoo / Nextcloud / WeCom / Weixin-ClawBot / Home Assistant) and work identity.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
"inject": [
|
|
29
29
|
"@deepseek-ai/dsh-client-runtime",
|
|
30
30
|
"@deepseek-ai/dsh-client-connection",
|
|
31
|
-
"@deepseek-ai/dsh-client-
|
|
31
|
+
"@deepseek-ai/dsh-client-locale",
|
|
32
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
33
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins"
|
|
32
34
|
],
|
|
33
35
|
"platform": "web"
|
|
34
36
|
}
|
|
@@ -36,13 +38,13 @@
|
|
|
36
38
|
"dependencies": {
|
|
37
39
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
38
40
|
"zod": "^4.4.3",
|
|
39
|
-
"@rezti/dsh-rez-ha-bridge": "0.1.
|
|
41
|
+
"@rezti/dsh-rez-ha-bridge": "0.1.4",
|
|
42
|
+
"@rezti/dsh-rez-sso": "0.1.4",
|
|
43
|
+
"@rezti/dsh-rez-nextcloud": "0.1.4",
|
|
40
44
|
"@rezti/dsh-rez-intent": "0.1.3",
|
|
41
|
-
"@rezti/dsh-rez-
|
|
42
|
-
"@rezti/dsh-rez-
|
|
43
|
-
"@rezti/dsh-rez-
|
|
44
|
-
"@rezti/dsh-rez-wechat": "0.1.3",
|
|
45
|
-
"@rezti/dsh-rez-token-manager": "0.1.3"
|
|
45
|
+
"@rezti/dsh-rez-odoo": "0.1.4",
|
|
46
|
+
"@rezti/dsh-rez-token-manager": "0.1.3",
|
|
47
|
+
"@rezti/dsh-rez-wechat": "0.1.4"
|
|
46
48
|
},
|
|
47
49
|
"peerDependencies": {
|
|
48
50
|
"react": "^18.2.0",
|
package/src/client/index.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser-half entry for dsh-rez-suite
|
|
3
|
-
* Registers locale dictionaries and
|
|
4
|
-
*
|
|
2
|
+
* Browser-half entry for dsh-rez-suite.
|
|
3
|
+
* Registers locale dictionaries and contributes a native Settings card
|
|
4
|
+
* (设置 → 插件 → 插件配置) plus a Plugins tab. Do not mount a sidebar
|
|
5
|
+
* takeover over the conversation column.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'
|
|
8
9
|
import type {} from '@deepseek-ai/dsh-client-locale/client'
|
|
10
|
+
import type {} from '@deepseek-ai/dsh-client-ui-settings/client'
|
|
9
11
|
import type {} from '@deepseek-ai/dsh-client-ui-slots'
|
|
10
|
-
import { RezApi } from './api.ts'
|
|
11
12
|
import { en, zh, type RezKey } from './locales.ts'
|
|
12
|
-
import {
|
|
13
|
-
import { PanelController } from './panel/controller.ts'
|
|
14
|
-
import { mountSidebarEntry } from './sidebar-entry.ts'
|
|
13
|
+
import { RezPluginCard, RezSettingsPage } from './settings-card.tsx'
|
|
15
14
|
|
|
16
15
|
const NS = 'dsh-rez-suite'
|
|
17
16
|
|
|
@@ -19,27 +18,40 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
19
18
|
interface LocaleNamespaceMap {
|
|
20
19
|
'dsh-rez-suite': RezKey
|
|
21
20
|
}
|
|
21
|
+
interface SlotMap {
|
|
22
|
+
'settings.plugin.item': {
|
|
23
|
+
kind: 'list'
|
|
24
|
+
scope: 'root'
|
|
25
|
+
owner: { children?: never }
|
|
26
|
+
}
|
|
27
|
+
'settings.plugins.tab': {
|
|
28
|
+
kind: 'list'
|
|
29
|
+
scope: 'root'
|
|
30
|
+
owner: { children?: never }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
22
33
|
}
|
|
23
34
|
|
|
24
35
|
export const inject = ['slots', 'locale']
|
|
25
36
|
|
|
26
|
-
export type { PanelControllerSnapshot } from './panel/controller.ts'
|
|
27
|
-
export type { RezPanelProps } from './panel/RezPanel.tsx'
|
|
28
37
|
export type { RezKey } from './locales.ts'
|
|
29
38
|
|
|
30
39
|
export function apply(ctx: ClientContext): void {
|
|
40
|
+
const t = ctx.locale.bind(NS)
|
|
31
41
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-rez-suite: dictionaries')
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({
|
|
44
|
+
name: 'settings.plugin.item',
|
|
45
|
+
id: 'rez-suite',
|
|
46
|
+
order: 40,
|
|
47
|
+
locale: NS,
|
|
48
|
+
}, RezPluginCard))
|
|
49
|
+
|
|
50
|
+
ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
|
|
51
|
+
name: 'settings.plugins.tab',
|
|
52
|
+
id: 'rez',
|
|
53
|
+
order: 20,
|
|
54
|
+
label: () => t('settings.title'),
|
|
55
|
+
locale: NS,
|
|
56
|
+
}, RezSettingsPage))
|
|
45
57
|
}
|
package/src/client/locales.ts
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
export const zh = {
|
|
6
6
|
'entry.label': 'Rez',
|
|
7
7
|
'entry.tooltip': 'Rez Suite 配置与审计面板',
|
|
8
|
+
'settings.title': 'ReZ-TI',
|
|
9
|
+
'settings.description': '公司 MCP(Odoo / Nextcloud / 企微 / HA)与个人微信扫码通道。',
|
|
8
10
|
'panel.title': 'Rez Suite',
|
|
9
11
|
'tab.config': '配置',
|
|
10
12
|
'tab.weixin': '微信',
|
|
@@ -99,6 +101,8 @@ export type RezKey = keyof typeof zh
|
|
|
99
101
|
export const en: Record<RezKey, string> = {
|
|
100
102
|
'entry.label': 'Rez',
|
|
101
103
|
'entry.tooltip': 'Rez Suite configuration and audit panel',
|
|
104
|
+
'settings.title': 'ReZ-TI',
|
|
105
|
+
'settings.description': 'Company MCP (Odoo / Nextcloud / WeCom / HA) and personal WeChat scan-and-chat.',
|
|
102
106
|
'panel.title': 'Rez Suite',
|
|
103
107
|
'tab.config': 'Config',
|
|
104
108
|
'tab.weixin': 'WeChat',
|
|
@@ -48,12 +48,12 @@ export function AuditTab({ api }: { api: RezApi }) {
|
|
|
48
48
|
</div>
|
|
49
49
|
{error !== '' && <div className={css.error}>{error}</div>}
|
|
50
50
|
<div className={css.cards}>
|
|
51
|
-
<div className={css.
|
|
52
|
-
<div className={css.
|
|
53
|
-
<div className={css.
|
|
54
|
-
<div className={css.
|
|
55
|
-
<div className={css.
|
|
56
|
-
<div className={css.
|
|
51
|
+
<div className={css.stat}><div className={css.cardLabel}>{tt('audit.totalCalls')}</div><div className={css.cardValue}>{audit.totalCalls}</div></div>
|
|
52
|
+
<div className={css.stat}><div className={css.cardLabel}>{tt('audit.inputTokens')}</div><div className={css.cardValue}>{audit.totalInputTokens}</div></div>
|
|
53
|
+
<div className={css.stat}><div className={css.cardLabel}>{tt('audit.outputTokens')}</div><div className={css.cardValue}>{audit.totalOutputTokens}</div></div>
|
|
54
|
+
<div className={css.stat}><div className={css.cardLabel}>{tt('audit.totalCost')}</div><div className={css.cardValue}>{audit.totalCost.toFixed(4)}</div></div>
|
|
55
|
+
<div className={css.stat}><div className={css.cardLabel}>{tt('audit.monthCost')}</div><div className={css.cardValue}>{audit.monthCost.toFixed(4)}</div></div>
|
|
56
|
+
<div className={css.stat}><div className={css.cardLabel}>{tt('audit.budget')}</div><div className={css.cardValue}>{audit.monthlyBudget.toFixed(2)}</div></div>
|
|
57
57
|
</div>
|
|
58
58
|
<div className={css.tableWrap}>
|
|
59
59
|
<table className={css.table}>
|