@duyanhdev/mvp-ifs-ui-kit 21.0.0
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/.editorconfig +16 -0
- package/.gitmodules +3 -0
- package/.postcssrc.json +5 -0
- package/.prettierignore +14 -0
- package/.prettierrc.json +29 -0
- package/LICENSE.md +21 -0
- package/README.md +59 -0
- package/angular.json +98 -0
- package/eslint.config.js +89 -0
- package/package.json +59 -0
- package/public/demo/images/flag/flag_placeholder.png +0 -0
- package/public/demo/images/footer-image.gif +0 -0
- package/public/demo/images/galleria/galleria1.jpg +0 -0
- package/public/demo/images/galleria/galleria10.jpg +0 -0
- package/public/demo/images/galleria/galleria10s.jpg +0 -0
- package/public/demo/images/galleria/galleria11.jpg +0 -0
- package/public/demo/images/galleria/galleria11s.jpg +0 -0
- package/public/demo/images/galleria/galleria12.jpg +0 -0
- package/public/demo/images/galleria/galleria12s.jpg +0 -0
- package/public/demo/images/galleria/galleria13.jpg +0 -0
- package/public/demo/images/galleria/galleria13s.jpg +0 -0
- package/public/demo/images/galleria/galleria14.jpg +0 -0
- package/public/demo/images/galleria/galleria14s.jpg +0 -0
- package/public/demo/images/galleria/galleria15.jpg +0 -0
- package/public/demo/images/galleria/galleria15s.jpg +0 -0
- package/public/demo/images/galleria/galleria1s.jpg +0 -0
- package/public/demo/images/galleria/galleria2.jpg +0 -0
- package/public/demo/images/galleria/galleria2s.jpg +0 -0
- package/public/demo/images/galleria/galleria3.jpg +0 -0
- package/public/demo/images/galleria/galleria3s.jpg +0 -0
- package/public/demo/images/galleria/galleria4.jpg +0 -0
- package/public/demo/images/galleria/galleria4s.jpg +0 -0
- package/public/demo/images/galleria/galleria5.jpg +0 -0
- package/public/demo/images/galleria/galleria5s.jpg +0 -0
- package/public/demo/images/galleria/galleria6.jpg +0 -0
- package/public/demo/images/galleria/galleria6s.jpg +0 -0
- package/public/demo/images/galleria/galleria7.jpg +0 -0
- package/public/demo/images/galleria/galleria7s.jpg +0 -0
- package/public/demo/images/galleria/galleria8.jpg +0 -0
- package/public/demo/images/galleria/galleria8s.jpg +0 -0
- package/public/demo/images/galleria/galleria9.jpg +0 -0
- package/public/demo/images/galleria/galleria9s.jpg +0 -0
- package/public/demo/images/product/bamboo-watch.jpg +0 -0
- package/public/demo/images/product/black-watch.jpg +0 -0
- package/public/demo/images/product/blue-band.jpg +0 -0
- package/public/demo/images/product/blue-t-shirt.jpg +0 -0
- package/public/demo/images/product/bracelet.jpg +0 -0
- package/public/demo/images/product/brown-purse.jpg +0 -0
- package/public/demo/images/product/chakra-bracelet.jpg +0 -0
- package/public/demo/images/product/galaxy-earrings.jpg +0 -0
- package/public/demo/images/product/game-controller.jpg +0 -0
- package/public/demo/images/product/gaming-set.jpg +0 -0
- package/public/demo/images/product/gold-phone-case.jpg +0 -0
- package/public/demo/images/product/green-earbuds.jpg +0 -0
- package/public/demo/images/product/green-t-shirt.jpg +0 -0
- package/public/demo/images/product/grey-t-shirt.jpg +0 -0
- package/public/demo/images/product/headphones.jpg +0 -0
- package/public/demo/images/product/light-green-t-shirt.jpg +0 -0
- package/public/demo/images/product/lime-band.jpg +0 -0
- package/public/demo/images/product/mini-speakers.jpg +0 -0
- package/public/demo/images/product/painted-phone-case.jpg +0 -0
- package/public/demo/images/product/pink-band.jpg +0 -0
- package/public/demo/images/product/pink-purse.jpg +0 -0
- package/public/demo/images/product/product-placeholder.svg +10 -0
- package/public/demo/images/product/purple-band.jpg +0 -0
- package/public/demo/images/product/purple-gemstone-necklace.jpg +0 -0
- package/public/demo/images/product/purple-t-shirt.jpg +0 -0
- package/public/demo/images/product/shoes.jpg +0 -0
- package/public/demo/images/product/sneakers.jpg +0 -0
- package/public/demo/images/product/teal-t-shirt.jpg +0 -0
- package/public/demo/images/product/yellow-earbuds.jpg +0 -0
- package/public/demo/images/product/yoga-mat.jpg +0 -0
- package/public/demo/images/product/yoga-set.jpg +0 -0
- package/src/app/layout/component/configurator/app.configurator.html +48 -0
- package/src/app/layout/component/configurator/app.configurator.ts +396 -0
- package/src/app/layout/component/floatingconfigurator/app.floatingconfigurator.ts +31 -0
- package/src/app/layout/component/footer/app.footer.scss +52 -0
- package/src/app/layout/component/footer/app.footer.ts +26 -0
- package/src/app/layout/component/layout/app.layout.ts +50 -0
- package/src/app/layout/component/menu/app.menu.html +7 -0
- package/src/app/layout/component/menu/app.menu.scss +13 -0
- package/src/app/layout/component/menu/app.menu.ts +90 -0
- package/src/app/layout/component/menuitem/app.menuitem.html +56 -0
- package/src/app/layout/component/menuitem/app.menuitem.scss +218 -0
- package/src/app/layout/component/menuitem/app.menuitem.ts +126 -0
- package/src/app/layout/component/sidebar/app.sidebar.html +3 -0
- package/src/app/layout/component/sidebar/app.sidebar.scss +0 -0
- package/src/app/layout/component/sidebar/app.sidebar.ts +106 -0
- package/src/app/layout/component/topbar/app.topbar.html +190 -0
- package/src/app/layout/component/topbar/app.topbar.scss +8 -0
- package/src/app/layout/component/topbar/app.topbar.ts +68 -0
- package/src/app/layout/service/layout.service.ts +117 -0
- package/src/app/pages/auth/access.ts +32 -0
- package/src/app/pages/auth/auth.routes.ts +10 -0
- package/src/app/pages/auth/error.ts +32 -0
- package/src/app/pages/auth/login.ts +71 -0
- package/src/app/pages/crud/crud.ts +387 -0
- package/src/app/pages/dashboard/dashboard.css +778 -0
- package/src/app/pages/dashboard/dashboard.html +191 -0
- package/src/app/pages/dashboard/dashboard.ts +348 -0
- package/src/app/pages/documentation/documentation.ts +73 -0
- package/src/app/pages/empty/empty.ts +11 -0
- package/src/app/pages/landing/components/featureswidget.ts +139 -0
- package/src/app/pages/landing/components/footerwidget.ts +73 -0
- package/src/app/pages/landing/components/herowidget.ts +25 -0
- package/src/app/pages/landing/components/highlightswidget.ts +46 -0
- package/src/app/pages/landing/components/pricingwidget.ts +119 -0
- package/src/app/pages/landing/components/topbarwidget.component.ts +68 -0
- package/src/app/pages/landing/landing.ts +31 -0
- package/src/app/pages/notfound/notfound.ts +68 -0
- package/src/app/pages/pages.routes.ts +17 -0
- package/src/app/pages/profile/profile.html +57 -0
- package/src/app/pages/profile/profile.scss +145 -0
- package/src/app/pages/profile/profile.ts +19 -0
- package/src/app/pages/service/country.service.ts +255 -0
- package/src/app/pages/service/customer.service.ts +9057 -0
- package/src/app/pages/service/icon.service.ts +23 -0
- package/src/app/pages/service/node.service.ts +816 -0
- package/src/app/pages/service/photo.service.ts +103 -0
- package/src/app/pages/service/product.service.ts +1322 -0
- package/src/app/pages/tickets/tickets-create/tickets-create.html +140 -0
- package/src/app/pages/tickets/tickets-create/tickets-create.scss +617 -0
- package/src/app/pages/tickets/tickets-create/tickets-create.ts +104 -0
- package/src/app/pages/tickets/tickets-list/ticket-list.html +150 -0
- package/src/app/pages/tickets/tickets-list/ticket-list.scss +392 -0
- package/src/app/pages/tickets/tickets-list/ticket-list.ts +178 -0
- package/src/app/pages/uikit/buttondemo.ts +254 -0
- package/src/app/pages/uikit/chartdemo.ts +290 -0
- package/src/app/pages/uikit/filedemo.ts +52 -0
- package/src/app/pages/uikit/formlayoutdemo.ts +129 -0
- package/src/app/pages/uikit/inputdemo.ts +339 -0
- package/src/app/pages/uikit/listdemo.ts +217 -0
- package/src/app/pages/uikit/mediademo.ts +1021 -0
- package/src/app/pages/uikit/menudemo.ts +540 -0
- package/src/app/pages/uikit/messagesdemo.ts +101 -0
- package/src/app/pages/uikit/miscdemo.ts +192 -0
- package/src/app/pages/uikit/overlaydemo.ts +235 -0
- package/src/app/pages/uikit/panelsdemo.ts +235 -0
- package/src/app/pages/uikit/tabledemo.ts +568 -0
- package/src/app/pages/uikit/timelinedemo.ts +141 -0
- package/src/app/pages/uikit/treedemo.ts +75 -0
- package/src/app/pages/uikit/uikit.routes.ts +35 -0
- package/src/app.component.ts +22 -0
- package/src/app.config.ts +23 -0
- package/src/app.routes.ts +23 -0
- package/src/assets/demo/code.scss +17 -0
- package/src/assets/demo/demo.scss +2 -0
- package/src/assets/demo/flags/flags.css +984 -0
- package/src/assets/layout/_core.scss +24 -0
- package/src/assets/layout/_footer.scss +8 -0
- package/src/assets/layout/_main.scss +21 -0
- package/src/assets/layout/_menu.scss +159 -0
- package/src/assets/layout/_mixins.scss +15 -0
- package/src/assets/layout/_preloading.scss +47 -0
- package/src/assets/layout/_responsive.scss +111 -0
- package/src/assets/layout/_topbar.scss +201 -0
- package/src/assets/layout/_typography.scss +68 -0
- package/src/assets/layout/_utils.scss +25 -0
- package/src/assets/layout/layout.scss +13 -0
- package/src/assets/layout/variables/_common.scss +21 -0
- package/src/assets/layout/variables/_dark.scss +5 -0
- package/src/assets/layout/variables/_light.scss +5 -0
- package/src/assets/styles.scss +4 -0
- package/src/assets/tailwind.css +32 -0
- package/src/index.html +15 -0
- package/src/main.ts +5 -0
- package/tsconfig.app.json +15 -0
- package/tsconfig.json +33 -0
- package/tsconfig.spec.json +15 -0
- package/vercel.json +9 -0
|
@@ -0,0 +1,1021 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, OnInit } from '@angular/core';
|
|
3
|
+
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import { ButtonModule } from 'primeng/button';
|
|
5
|
+
import { InputTextModule } from 'primeng/inputtext';
|
|
6
|
+
import { SelectModule } from 'primeng/select';
|
|
7
|
+
import { DatePickerModule } from 'primeng/datepicker';
|
|
8
|
+
import { TextareaModule } from 'primeng/textarea';
|
|
9
|
+
import { CheckboxModule } from 'primeng/checkbox';
|
|
10
|
+
|
|
11
|
+
interface City {
|
|
12
|
+
name: string;
|
|
13
|
+
code: string;
|
|
14
|
+
}
|
|
15
|
+
interface Code {
|
|
16
|
+
name: string;
|
|
17
|
+
code: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Component({
|
|
21
|
+
selector: 'app-media-demo',
|
|
22
|
+
standalone: true,
|
|
23
|
+
imports: [CommonModule, FormsModule, ButtonModule, InputTextModule, SelectModule, DatePickerModule, TextareaModule, CheckboxModule],
|
|
24
|
+
styles: `
|
|
25
|
+
/* ══════════════════════════════════
|
|
26
|
+
LIGHT MODE TOKENS
|
|
27
|
+
══════════════════════════════════ */
|
|
28
|
+
:host {
|
|
29
|
+
--blue-dark: #1e3a8a;
|
|
30
|
+
--blue-main: #2563eb;
|
|
31
|
+
--blue-mid: #3b82f6;
|
|
32
|
+
--blue-light: #93c5fd;
|
|
33
|
+
--blue-soft: #eff6ff;
|
|
34
|
+
--blue-ring: rgba(37, 99, 235, 0.14);
|
|
35
|
+
|
|
36
|
+
--bg-page: #f1f5f9;
|
|
37
|
+
--bg-body: #ffffff;
|
|
38
|
+
--bg-field: #ffffff;
|
|
39
|
+
--bg-card: #ffffff;
|
|
40
|
+
--bg-card-hover: #f8faff;
|
|
41
|
+
|
|
42
|
+
--border-color: #e5e7eb;
|
|
43
|
+
--border-input: #d1d5db;
|
|
44
|
+
|
|
45
|
+
--text-primary: #111827;
|
|
46
|
+
--text-label: #6b7280;
|
|
47
|
+
--text-item: #374151;
|
|
48
|
+
--text-placeholder: #9ca3af;
|
|
49
|
+
|
|
50
|
+
--divider: linear-gradient(90deg, #bfdbfe, transparent);
|
|
51
|
+
--shadow-body: 0 8px 32px rgba(0, 0, 0, 0.07);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* ══════════════════════════════════
|
|
55
|
+
DARK MODE TOKENS
|
|
56
|
+
══════════════════════════════════ */
|
|
57
|
+
:host-context(.app-dark) {
|
|
58
|
+
--blue-dark: #1d4ed8;
|
|
59
|
+
--blue-main: #3b82f6;
|
|
60
|
+
--blue-mid: #60a5fa;
|
|
61
|
+
--blue-light: #93c5fd;
|
|
62
|
+
--blue-soft: rgba(59, 130, 246, 0.12);
|
|
63
|
+
--blue-ring: rgba(59, 130, 246, 0.2);
|
|
64
|
+
|
|
65
|
+
--bg-page: #0f172a;
|
|
66
|
+
--bg-body: #1e293b;
|
|
67
|
+
--bg-field: #0f172a;
|
|
68
|
+
--bg-card: #1e293b;
|
|
69
|
+
--bg-card-hover: #263548;
|
|
70
|
+
|
|
71
|
+
--border-color: #334155;
|
|
72
|
+
--border-input: #334155;
|
|
73
|
+
|
|
74
|
+
--text-primary: #f1f5f9;
|
|
75
|
+
--text-label: #94a3b8;
|
|
76
|
+
--text-item: #cbd5e1;
|
|
77
|
+
--text-placeholder: #475569;
|
|
78
|
+
|
|
79
|
+
--divider: linear-gradient(90deg, rgba(59, 130, 246, 0.3), transparent);
|
|
80
|
+
--shadow-body: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* ══════════════════════════════════
|
|
84
|
+
LAYOUT
|
|
85
|
+
══════════════════════════════════ */
|
|
86
|
+
.page-wrapper {
|
|
87
|
+
max-width: 1200px;
|
|
88
|
+
margin: 0 auto;
|
|
89
|
+
padding: 32px 16px 64px;
|
|
90
|
+
background: var(--bg-page);
|
|
91
|
+
min-height: 100vh;
|
|
92
|
+
transition: background 0.3s;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* ── Header ── */
|
|
96
|
+
.form-header {
|
|
97
|
+
background: linear-gradient(135deg, var(--blue-dark) 0%, var(--blue-main) 55%, var(--blue-mid) 100%);
|
|
98
|
+
border-radius: 20px 20px 0 0;
|
|
99
|
+
padding: 32px 40px;
|
|
100
|
+
position: relative;
|
|
101
|
+
overflow: hidden;
|
|
102
|
+
}
|
|
103
|
+
.form-header::before {
|
|
104
|
+
content: '';
|
|
105
|
+
position: absolute;
|
|
106
|
+
inset: 0;
|
|
107
|
+
background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23ffffff' fill-opacity='0.04'%3E%3Ccircle cx='30' cy='30' r='20'/%3E%3C/g%3E%3C/svg%3E");
|
|
108
|
+
}
|
|
109
|
+
.form-header h1 {
|
|
110
|
+
font-size: clamp(15px, 2.5vw, 21px);
|
|
111
|
+
font-weight: 800;
|
|
112
|
+
color: #fff;
|
|
113
|
+
text-align: center;
|
|
114
|
+
letter-spacing: 0.5px;
|
|
115
|
+
position: relative;
|
|
116
|
+
margin: 0;
|
|
117
|
+
}
|
|
118
|
+
.form-header p {
|
|
119
|
+
text-align: center;
|
|
120
|
+
color: rgba(255, 255, 255, 0.65);
|
|
121
|
+
font-size: 13px;
|
|
122
|
+
margin: 6px 0 0;
|
|
123
|
+
position: relative;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* ── Body ── */
|
|
127
|
+
.form-body {
|
|
128
|
+
background: var(--bg-body);
|
|
129
|
+
border-radius: 0 0 20px 20px;
|
|
130
|
+
border: 1px solid var(--border-color);
|
|
131
|
+
border-top: none;
|
|
132
|
+
padding: 32px 40px 40px;
|
|
133
|
+
box-shadow: var(--shadow-body);
|
|
134
|
+
transition:
|
|
135
|
+
background 0.3s,
|
|
136
|
+
border-color 0.3s;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* ── Section title ── */
|
|
140
|
+
.section-title {
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
gap: 12px;
|
|
144
|
+
margin-bottom: 16px;
|
|
145
|
+
margin-top: 28px;
|
|
146
|
+
&:first-child {
|
|
147
|
+
margin-top: 0;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
.section-num {
|
|
151
|
+
width: 32px;
|
|
152
|
+
height: 32px;
|
|
153
|
+
border-radius: 50%;
|
|
154
|
+
background: linear-gradient(135deg, var(--blue-dark), var(--blue-main));
|
|
155
|
+
color: #fff;
|
|
156
|
+
font-size: 13px;
|
|
157
|
+
font-weight: 700;
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
justify-content: center;
|
|
161
|
+
flex-shrink: 0;
|
|
162
|
+
box-shadow: 0 4px 12px var(--blue-ring);
|
|
163
|
+
}
|
|
164
|
+
.section-name {
|
|
165
|
+
font-size: 14px;
|
|
166
|
+
font-weight: 700;
|
|
167
|
+
color: var(--text-primary);
|
|
168
|
+
letter-spacing: 0.4px;
|
|
169
|
+
text-transform: uppercase;
|
|
170
|
+
}
|
|
171
|
+
.section-divider {
|
|
172
|
+
height: 1px;
|
|
173
|
+
background: var(--divider);
|
|
174
|
+
margin-bottom: 20px;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* ── Fields ── */
|
|
178
|
+
.field-group {
|
|
179
|
+
display: grid;
|
|
180
|
+
grid-template-columns: 1fr 1fr;
|
|
181
|
+
gap: 18px;
|
|
182
|
+
margin-bottom: 8px;
|
|
183
|
+
}
|
|
184
|
+
.field {
|
|
185
|
+
display: flex;
|
|
186
|
+
flex-direction: column;
|
|
187
|
+
gap: 6px;
|
|
188
|
+
}
|
|
189
|
+
.field label {
|
|
190
|
+
font-size: 11px;
|
|
191
|
+
font-weight: 700;
|
|
192
|
+
color: var(--text-label);
|
|
193
|
+
text-transform: uppercase;
|
|
194
|
+
letter-spacing: 0.7px;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
:host ::ng-deep {
|
|
198
|
+
/* ── Input ── */
|
|
199
|
+
.p-inputtext {
|
|
200
|
+
background: var(--bg-field) !important;
|
|
201
|
+
color: var(--text-primary) !important;
|
|
202
|
+
border-color: var(--border-input) !important;
|
|
203
|
+
border-radius: 10px !important;
|
|
204
|
+
font-size: 13.5px !important;
|
|
205
|
+
padding: 10px 14px !important;
|
|
206
|
+
width: 100% !important;
|
|
207
|
+
transition:
|
|
208
|
+
border-color 0.2s,
|
|
209
|
+
box-shadow 0.2s,
|
|
210
|
+
background 0.3s !important;
|
|
211
|
+
|
|
212
|
+
&:hover {
|
|
213
|
+
border-color: var(--blue-light) !important;
|
|
214
|
+
}
|
|
215
|
+
&:focus {
|
|
216
|
+
border-color: var(--blue-main) !important;
|
|
217
|
+
box-shadow: 0 0 0 3px var(--blue-ring) !important;
|
|
218
|
+
}
|
|
219
|
+
&::placeholder {
|
|
220
|
+
color: var(--text-placeholder) !important;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* ── Select ── */
|
|
225
|
+
.p-select {
|
|
226
|
+
background: var(--bg-field) !important;
|
|
227
|
+
border-color: var(--border-input) !important;
|
|
228
|
+
border-radius: 10px !important;
|
|
229
|
+
width: 100% !important;
|
|
230
|
+
transition:
|
|
231
|
+
border-color 0.2s,
|
|
232
|
+
background 0.3s !important;
|
|
233
|
+
|
|
234
|
+
&:hover {
|
|
235
|
+
border-color: var(--blue-light) !important;
|
|
236
|
+
}
|
|
237
|
+
&.p-focus {
|
|
238
|
+
border-color: var(--blue-main) !important;
|
|
239
|
+
box-shadow: 0 0 0 3px var(--blue-ring) !important;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.p-select-label {
|
|
243
|
+
color: var(--text-primary) !important;
|
|
244
|
+
&.p-placeholder {
|
|
245
|
+
color: var(--text-placeholder) !important;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
.p-select-dropdown {
|
|
249
|
+
color: var(--text-label) !important;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* Select panel dropdown */
|
|
254
|
+
.p-select-overlay {
|
|
255
|
+
background: var(--bg-body) !important;
|
|
256
|
+
border-color: var(--border-color) !important;
|
|
257
|
+
border-radius: 12px !important;
|
|
258
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15) !important;
|
|
259
|
+
|
|
260
|
+
.p-select-option {
|
|
261
|
+
color: var(--text-item) !important;
|
|
262
|
+
&:hover,
|
|
263
|
+
&.p-focus {
|
|
264
|
+
background: var(--blue-soft) !important;
|
|
265
|
+
color: var(--blue-main) !important;
|
|
266
|
+
}
|
|
267
|
+
&.p-select-option-selected {
|
|
268
|
+
background: var(--blue-soft) !important;
|
|
269
|
+
color: var(--blue-main) !important;
|
|
270
|
+
font-weight: 600 !important;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/* ── Datepicker ── */
|
|
276
|
+
input.p-datepicker-input {
|
|
277
|
+
background: var(--bg-field) !important;
|
|
278
|
+
color: var(--text-primary) !important;
|
|
279
|
+
border-color: var(--border-input) !important;
|
|
280
|
+
border-radius: 10px !important;
|
|
281
|
+
width: 100% !important;
|
|
282
|
+
&:focus {
|
|
283
|
+
border-color: var(--blue-main) !important;
|
|
284
|
+
box-shadow: 0 0 0 3px var(--blue-ring) !important;
|
|
285
|
+
}
|
|
286
|
+
&::placeholder {
|
|
287
|
+
color: var(--text-placeholder) !important;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
.p-datepicker-panel {
|
|
291
|
+
background: var(--bg-body) !important;
|
|
292
|
+
border-color: var(--border-color) !important;
|
|
293
|
+
border-radius: 12px !important;
|
|
294
|
+
|
|
295
|
+
.p-datepicker-header {
|
|
296
|
+
background: var(--bg-body) !important;
|
|
297
|
+
color: var(--text-primary) !important;
|
|
298
|
+
border-color: var(--border-color) !important;
|
|
299
|
+
}
|
|
300
|
+
.p-datepicker-day-view .p-datepicker-day-cell span {
|
|
301
|
+
color: var(--text-item) !important;
|
|
302
|
+
&:hover {
|
|
303
|
+
background: var(--blue-soft) !important;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
.p-datepicker-day-cell.p-datepicker-today span {
|
|
307
|
+
background: var(--blue-soft) !important;
|
|
308
|
+
color: var(--blue-main) !important;
|
|
309
|
+
font-weight: 700 !important;
|
|
310
|
+
}
|
|
311
|
+
.p-datepicker-day-cell.p-datepicker-selected span {
|
|
312
|
+
background: var(--blue-main) !important;
|
|
313
|
+
color: #fff !important;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* ── Textarea ── */
|
|
318
|
+
.p-textarea {
|
|
319
|
+
background: var(--bg-field) !important;
|
|
320
|
+
color: var(--text-primary) !important;
|
|
321
|
+
border-color: var(--border-input) !important;
|
|
322
|
+
border-radius: 10px !important;
|
|
323
|
+
width: 100% !important;
|
|
324
|
+
font-size: 13.5px !important;
|
|
325
|
+
resize: vertical !important;
|
|
326
|
+
transition:
|
|
327
|
+
border-color 0.2s,
|
|
328
|
+
background 0.3s !important;
|
|
329
|
+
|
|
330
|
+
&:focus {
|
|
331
|
+
border-color: var(--blue-main) !important;
|
|
332
|
+
box-shadow: 0 0 0 3px var(--blue-ring) !important;
|
|
333
|
+
}
|
|
334
|
+
&::placeholder {
|
|
335
|
+
color: var(--text-placeholder) !important;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* ── Button ── */
|
|
340
|
+
.p-button:not(.p-button-outlined) {
|
|
341
|
+
background: var(--blue-main) !important;
|
|
342
|
+
border-color: var(--blue-main) !important;
|
|
343
|
+
color: #fff !important;
|
|
344
|
+
&:hover {
|
|
345
|
+
background: var(--blue-dark) !important;
|
|
346
|
+
border-color: var(--blue-dark) !important;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
.p-button-outlined {
|
|
350
|
+
background: transparent !important;
|
|
351
|
+
color: var(--blue-main) !important;
|
|
352
|
+
border-color: var(--blue-main) !important;
|
|
353
|
+
&:hover {
|
|
354
|
+
background: var(--blue-soft) !important;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/* ── Checkbox ── */
|
|
359
|
+
.p-checkbox .p-checkbox-box {
|
|
360
|
+
background: var(--bg-field) !important;
|
|
361
|
+
border-color: var(--border-input) !important;
|
|
362
|
+
transition:
|
|
363
|
+
background 0.2s,
|
|
364
|
+
border-color 0.2s !important;
|
|
365
|
+
}
|
|
366
|
+
.p-checkbox:not(.p-checkbox-checked):hover .p-checkbox-box {
|
|
367
|
+
border-color: var(--blue-light) !important;
|
|
368
|
+
}
|
|
369
|
+
.p-checkbox.p-checkbox-checked .p-checkbox-box {
|
|
370
|
+
background: var(--blue-main) !important;
|
|
371
|
+
border-color: var(--blue-main) !important;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* ── Purchase cards ── */
|
|
376
|
+
.purchase-grid {
|
|
377
|
+
display: grid;
|
|
378
|
+
grid-template-columns: repeat(4, 1fr);
|
|
379
|
+
gap: 14px;
|
|
380
|
+
margin-bottom: 8px;
|
|
381
|
+
}
|
|
382
|
+
.purchase-card {
|
|
383
|
+
border: 1.5px solid var(--border-color);
|
|
384
|
+
border-radius: 14px;
|
|
385
|
+
overflow: hidden;
|
|
386
|
+
display: flex;
|
|
387
|
+
flex-direction: column;
|
|
388
|
+
background: var(--bg-card);
|
|
389
|
+
transition:
|
|
390
|
+
border-color 0.2s,
|
|
391
|
+
box-shadow 0.2s,
|
|
392
|
+
background 0.3s;
|
|
393
|
+
|
|
394
|
+
&:hover {
|
|
395
|
+
border-color: var(--blue-light);
|
|
396
|
+
box-shadow: 0 4px 16px var(--blue-ring);
|
|
397
|
+
background: var(--bg-card-hover);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
.purchase-header {
|
|
401
|
+
display: flex;
|
|
402
|
+
align-items: center;
|
|
403
|
+
gap: 10px;
|
|
404
|
+
padding: 11px 14px;
|
|
405
|
+
background: linear-gradient(135deg, var(--blue-dark) 0%, var(--blue-main) 55%, var(--blue-mid) 100%);
|
|
406
|
+
flex-shrink: 0;
|
|
407
|
+
}
|
|
408
|
+
.purchase-num {
|
|
409
|
+
width: 22px;
|
|
410
|
+
height: 22px;
|
|
411
|
+
background: rgba(255, 255, 255, 0.2);
|
|
412
|
+
border: 1.5px solid rgba(255, 255, 255, 0.35);
|
|
413
|
+
border-radius: 50%;
|
|
414
|
+
color: #fff;
|
|
415
|
+
font-size: 11px;
|
|
416
|
+
font-weight: 700;
|
|
417
|
+
display: flex;
|
|
418
|
+
align-items: center;
|
|
419
|
+
justify-content: center;
|
|
420
|
+
flex-shrink: 0;
|
|
421
|
+
}
|
|
422
|
+
.purchase-title {
|
|
423
|
+
font-size: 11.5px;
|
|
424
|
+
font-weight: 700;
|
|
425
|
+
color: #fff;
|
|
426
|
+
text-transform: uppercase;
|
|
427
|
+
letter-spacing: 0.4px;
|
|
428
|
+
margin: 0;
|
|
429
|
+
line-height: 1.3;
|
|
430
|
+
}
|
|
431
|
+
.purchase-body {
|
|
432
|
+
padding: 10px 12px;
|
|
433
|
+
display: flex;
|
|
434
|
+
flex-direction: column;
|
|
435
|
+
gap: 6px;
|
|
436
|
+
background: var(--bg-card);
|
|
437
|
+
flex: 1;
|
|
438
|
+
transition: background 0.3s;
|
|
439
|
+
}
|
|
440
|
+
.check-item {
|
|
441
|
+
display: flex;
|
|
442
|
+
align-items: flex-start;
|
|
443
|
+
gap: 9px;
|
|
444
|
+
padding: 7px 9px;
|
|
445
|
+
border-radius: 8px;
|
|
446
|
+
cursor: pointer;
|
|
447
|
+
transition: background 0.15s;
|
|
448
|
+
|
|
449
|
+
&:hover {
|
|
450
|
+
background: var(--blue-soft);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
label {
|
|
454
|
+
font-size: 12.5px;
|
|
455
|
+
color: var(--text-item);
|
|
456
|
+
cursor: pointer;
|
|
457
|
+
line-height: 1.45;
|
|
458
|
+
margin: 0;
|
|
459
|
+
transition: color 0.15s;
|
|
460
|
+
}
|
|
461
|
+
&:has(.p-checkbox-checked) {
|
|
462
|
+
background: var(--blue-soft);
|
|
463
|
+
label {
|
|
464
|
+
color: var(--blue-main);
|
|
465
|
+
font-weight: 600;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/* ── Footer ── */
|
|
471
|
+
.form-footer {
|
|
472
|
+
display: flex;
|
|
473
|
+
justify-content: flex-end;
|
|
474
|
+
gap: 12px;
|
|
475
|
+
margin-top: 28px;
|
|
476
|
+
padding-top: 22px;
|
|
477
|
+
border-top: 1px solid var(--border-color);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/* ── Responsive ── */
|
|
481
|
+
@media (max-width: 900px) {
|
|
482
|
+
.purchase-grid {
|
|
483
|
+
grid-template-columns: repeat(2, 1fr);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
@media (max-width: 640px) {
|
|
487
|
+
.field-group {
|
|
488
|
+
grid-template-columns: 1fr;
|
|
489
|
+
}
|
|
490
|
+
.purchase-grid {
|
|
491
|
+
grid-template-columns: 1fr;
|
|
492
|
+
}
|
|
493
|
+
.form-body {
|
|
494
|
+
padding: 20px;
|
|
495
|
+
}
|
|
496
|
+
.form-header {
|
|
497
|
+
padding: 24px 20px;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
`,
|
|
501
|
+
template: `
|
|
502
|
+
<div class="page-wrapper">
|
|
503
|
+
<!-- Header -->
|
|
504
|
+
<div class="form-header">
|
|
505
|
+
<h1>Mẫu Form Ghi Nhận Lỗi Trong Công Việc Mua Hàng</h1>
|
|
506
|
+
<p>Vui lòng điền đầy đủ thông tin bên dưới</p>
|
|
507
|
+
</div>
|
|
508
|
+
|
|
509
|
+
<!-- Body -->
|
|
510
|
+
<div class="form-body">
|
|
511
|
+
<!-- Section 1 -->
|
|
512
|
+
<div class="section-title">
|
|
513
|
+
<div class="section-num">1</div>
|
|
514
|
+
<span class="section-name">Thông Tin Chung</span>
|
|
515
|
+
</div>
|
|
516
|
+
<div class="section-divider"></div>
|
|
517
|
+
<div class="field-group">
|
|
518
|
+
<div class="field">
|
|
519
|
+
<label>Người lập</label>
|
|
520
|
+
<input pInputText [(ngModel)]="form.nguoiLap" placeholder="Họ và tên người lập" />
|
|
521
|
+
</div>
|
|
522
|
+
<div class="field">
|
|
523
|
+
<label>Nhóm</label>
|
|
524
|
+
<p-select [options]="cities" [(ngModel)]="form.nhom" optionLabel="name" placeholder="Chọn nhóm" />
|
|
525
|
+
</div>
|
|
526
|
+
<div class="field">
|
|
527
|
+
<label>Vị trí / Chức danh</label>
|
|
528
|
+
<input pInputText [(ngModel)]="form.viTri" placeholder="Vd: Nhân viên mua hàng" />
|
|
529
|
+
</div>
|
|
530
|
+
<div class="field">
|
|
531
|
+
<label>Nhà cung cấp</label>
|
|
532
|
+
<p-select [options]="supplier" [(ngModel)]="form.nhaCungCap" optionLabel="name" placeholder="Chọn nhà cung cấp" />
|
|
533
|
+
</div>
|
|
534
|
+
<div class="field">
|
|
535
|
+
<label>Mã hàng</label>
|
|
536
|
+
<p-select [options]="productCode" [(ngModel)]="form.maHang" optionLabel="name" placeholder="Chọn mã hàng" />
|
|
537
|
+
</div>
|
|
538
|
+
<div class="field">
|
|
539
|
+
<label>Ngày phát sinh</label>
|
|
540
|
+
<p-datepicker [(ngModel)]="form.ngayPhatSinh" placeholder="dd/mm/yyyy" dateFormat="dd/mm/yy" [showIcon]="true" />
|
|
541
|
+
</div>
|
|
542
|
+
<div class="field">
|
|
543
|
+
<label>Tên lỗi</label>
|
|
544
|
+
<p-select [options]="cities" [(ngModel)]="form.tenLoi" optionLabel="name" placeholder="Chọn lỗi" />
|
|
545
|
+
</div>
|
|
546
|
+
<div class="field">
|
|
547
|
+
<label>Bộ phận liên quan</label>
|
|
548
|
+
<p-select [options]="cities" [(ngModel)]="form.boPhan" optionLabel="name" placeholder="Chọn bộ phận" />
|
|
549
|
+
</div>
|
|
550
|
+
</div>
|
|
551
|
+
|
|
552
|
+
<!-- Section 2 -->
|
|
553
|
+
<div class="section-title">
|
|
554
|
+
<div class="section-num">2</div>
|
|
555
|
+
<span class="section-name">Giai Đoạn Phát Sinh & Lỗi Phát Sinh</span>
|
|
556
|
+
</div>
|
|
557
|
+
<div class="section-divider"></div>
|
|
558
|
+
<div class="purchase-grid">
|
|
559
|
+
@for (group of purchaseGroups; track group.num) {
|
|
560
|
+
<div class="purchase-card">
|
|
561
|
+
<div class="purchase-header">
|
|
562
|
+
<span class="purchase-num">{{ group.num }}</span>
|
|
563
|
+
<p class="purchase-title">{{ group.title }}</p>
|
|
564
|
+
</div>
|
|
565
|
+
<div class="purchase-body">
|
|
566
|
+
@for (item of group.items; track item.id) {
|
|
567
|
+
<div class="check-item">
|
|
568
|
+
<p-checkbox [inputId]="item.id" [name]="'group' + group.num" [value]="item.value" [(ngModel)]="selected" />
|
|
569
|
+
<label [for]="item.id">{{ item.label }}</label>
|
|
570
|
+
</div>
|
|
571
|
+
}
|
|
572
|
+
</div>
|
|
573
|
+
</div>
|
|
574
|
+
}
|
|
575
|
+
</div>
|
|
576
|
+
|
|
577
|
+
<!-- Section 3 -->
|
|
578
|
+
<div class="section-title">
|
|
579
|
+
<div class="section-num">3</div>
|
|
580
|
+
<span class="section-name">Mô Tả Chi Tiết Lỗi</span>
|
|
581
|
+
</div>
|
|
582
|
+
<div class="section-divider"></div>
|
|
583
|
+
<div class="field">
|
|
584
|
+
<label>Nội dung mô tả</label>
|
|
585
|
+
<textarea pTextarea [(ngModel)]="form.moTa" rows="4" placeholder="Mô tả chi tiết tình huống xảy ra lỗi…"> </textarea>
|
|
586
|
+
</div>
|
|
587
|
+
|
|
588
|
+
<!-- Section 4 -->
|
|
589
|
+
<div class="section-title">
|
|
590
|
+
<div class="section-num">4</div>
|
|
591
|
+
<span class="section-name">Phân loại NGUYÊN NHÂN (Fishbone 6M)</span>
|
|
592
|
+
</div>
|
|
593
|
+
<div class="section-divider"></div>
|
|
594
|
+
<div class="purchase-grid">
|
|
595
|
+
@for (group of reason; track group.num) {
|
|
596
|
+
<div class="purchase-card">
|
|
597
|
+
<div class="check-item">
|
|
598
|
+
<p-checkbox [inputId]="'group' + group.num" [name]="'group' + group.num" [value]="group.title" [(ngModel)]="selected" />
|
|
599
|
+
<label [for]="group.num">{{ group.title }}</label>
|
|
600
|
+
</div>
|
|
601
|
+
</div>
|
|
602
|
+
}
|
|
603
|
+
</div>
|
|
604
|
+
|
|
605
|
+
<!-- Section 5 -->
|
|
606
|
+
<div class="section-title">
|
|
607
|
+
<div class="section-num">5</div>
|
|
608
|
+
<span class="section-name">Ảnh hưởng/Hậu quả</span>
|
|
609
|
+
</div>
|
|
610
|
+
<div class="section-divider"></div>
|
|
611
|
+
<div class="purchase-grid">
|
|
612
|
+
@for (group of reason; track group.num) {
|
|
613
|
+
<div class="purchase-card">
|
|
614
|
+
<div class="check-item">
|
|
615
|
+
<p-checkbox [inputId]="'group' + group.num" [name]="'group' + group.num" [value]="group.title" [(ngModel)]="selected" />
|
|
616
|
+
<label [for]="group.num">{{ group.title }}</label>
|
|
617
|
+
</div>
|
|
618
|
+
</div>
|
|
619
|
+
}
|
|
620
|
+
</div>
|
|
621
|
+
|
|
622
|
+
<!-- Section 6 -->
|
|
623
|
+
<div class="section-title">
|
|
624
|
+
<div class="section-num">6</div>
|
|
625
|
+
<span class="section-name">Cách xử lý khi lỗi đã xảy ra</span>
|
|
626
|
+
</div>
|
|
627
|
+
<div class="section-divider"></div>
|
|
628
|
+
<div class="field">
|
|
629
|
+
<label>Nội dung mô tả</label>
|
|
630
|
+
<textarea pTextarea [(ngModel)]="form.moTa" rows="4" placeholder="Mô tả chi tiết tình huống xảy ra lỗi…"> </textarea>
|
|
631
|
+
|
|
632
|
+
<div class="mt-2 flex ">
|
|
633
|
+
<span class="text-black font-bold text-xl border-b-2 border-black dark:border-white">Xác nhận của cấp trên:</span>
|
|
634
|
+
|
|
635
|
+
@for (option of option; track option.value) {
|
|
636
|
+
<div class="purchase-card">
|
|
637
|
+
<div class="check-item">
|
|
638
|
+
<p-checkbox [inputId]="'option' + option.value" [name]="'option' + option.value" [value]="option.name" [(ngModel)]="selected" />
|
|
639
|
+
<label [for]="option.value">{{ option.name }}</label>
|
|
640
|
+
</div>
|
|
641
|
+
</div>
|
|
642
|
+
}
|
|
643
|
+
</div>
|
|
644
|
+
</div>
|
|
645
|
+
|
|
646
|
+
<!-- Section 7 -->
|
|
647
|
+
<div class="section-title">
|
|
648
|
+
<div class="section-num">7</div>
|
|
649
|
+
<span class="section-name">Đối sách</span>
|
|
650
|
+
</div>
|
|
651
|
+
<div class="section-divider"></div>
|
|
652
|
+
<div class="field">
|
|
653
|
+
<label>Nội dung mô tả</label>
|
|
654
|
+
<textarea pTextarea [(ngModel)]="form.moTa" rows="4" placeholder="Mô tả chi tiết tình huống xảy ra lỗi…"> </textarea>
|
|
655
|
+
<div class="mt-2 flex ">
|
|
656
|
+
<span class="text-black font-bold text-xl border-b-2 border-black dark:border-white">Xác nhận của cấp trên:</span>
|
|
657
|
+
|
|
658
|
+
@for (option of option; track option.value) {
|
|
659
|
+
<div class="purchase-card">
|
|
660
|
+
<div class="check-item">
|
|
661
|
+
<p-checkbox [inputId]="'option' + option.value" [name]="'option' + option.value" [value]="option.name" [(ngModel)]="selected" />
|
|
662
|
+
<label [for]="option.value">{{ option.name }}</label>
|
|
663
|
+
</div>
|
|
664
|
+
</div>
|
|
665
|
+
}
|
|
666
|
+
</div>
|
|
667
|
+
</div>
|
|
668
|
+
|
|
669
|
+
<!-- Section 8 -->
|
|
670
|
+
<div class="section-title">
|
|
671
|
+
<div class="section-num">8</div>
|
|
672
|
+
<span class="section-name"> Quy trình - quy định - biểu mẫu (tham khảo)</span>
|
|
673
|
+
</div>
|
|
674
|
+
<div class="section-divider"></div>
|
|
675
|
+
<div class="purchase-grid">
|
|
676
|
+
<div class="purchase-card">
|
|
677
|
+
<div class="purchase-header flex items-center">
|
|
678
|
+
<span class="purchase-num">1</span>
|
|
679
|
+
<p class="purchase-title">Tên quy trình - quy định</p>
|
|
680
|
+
</div>
|
|
681
|
+
<div class="flex flex-col gap-3">
|
|
682
|
+
<div *ngFor="let item of items; let i = index; trackBy: trackByIndex" class="flex items-center gap-2">
|
|
683
|
+
<input pInputText [(ngModel)]="items[i]" [name]="'item_' + i" placeholder="Nhập giá trị..." class="flex-1" />
|
|
684
|
+
|
|
685
|
+
<!-- Nút xóa — chỉ hiện khi có hơn 1 ô -->
|
|
686
|
+
<button
|
|
687
|
+
*ngIf="items.length > 1"
|
|
688
|
+
type="button"
|
|
689
|
+
(click)="removeItem(i)"
|
|
690
|
+
class="w-8 h-8 flex items-center justify-center
|
|
691
|
+
rounded-lg border border-black/15 text-gray-400
|
|
692
|
+
hover:bg-red-50 hover:border-red-300 hover:text-red-500
|
|
693
|
+
transition-all"
|
|
694
|
+
>
|
|
695
|
+
<i class="pi pi-minus text-xs"></i>
|
|
696
|
+
</button>
|
|
697
|
+
</div>
|
|
698
|
+
|
|
699
|
+
<!-- Nút thêm -->
|
|
700
|
+
<button
|
|
701
|
+
type="button"
|
|
702
|
+
(click)="addItem()"
|
|
703
|
+
class="flex items-center gap-2 px-4 py-2 w-fit
|
|
704
|
+
rounded-lg border border-dashed border-black/20
|
|
705
|
+
text-sm text-gray-400 font-medium
|
|
706
|
+
hover:border-black/40 hover:text-black
|
|
707
|
+
transition-all dark:border-white/20
|
|
708
|
+
dark:hover:border-white/50 dark:hover:text-white"
|
|
709
|
+
>
|
|
710
|
+
<i class="pi pi-plus text-xs"></i>
|
|
711
|
+
Thêm dòng
|
|
712
|
+
</button>
|
|
713
|
+
</div>
|
|
714
|
+
</div>
|
|
715
|
+
<div class="purchase-card">
|
|
716
|
+
<div class="purchase-header">
|
|
717
|
+
<span class="purchase-num">2</span>
|
|
718
|
+
<p class="purchase-title">Hiện trạng</p>
|
|
719
|
+
</div>
|
|
720
|
+
<div class="flex flex-col gap-3">
|
|
721
|
+
<div *ngFor="let item of items; let i = index; trackBy: trackByIndex" class="flex items-center gap-2">
|
|
722
|
+
<input pInputText [(ngModel)]="items[i]" [name]="'item_' + i" placeholder="Nhập giá trị..." class="flex-1" />
|
|
723
|
+
|
|
724
|
+
<!-- Nút xóa — chỉ hiện khi có hơn 1 ô -->
|
|
725
|
+
<button
|
|
726
|
+
*ngIf="items.length > 1"
|
|
727
|
+
type="button"
|
|
728
|
+
(click)="removeItem(i)"
|
|
729
|
+
class="w-8 h-8 flex items-center justify-center
|
|
730
|
+
rounded-lg border border-black/15 text-gray-400
|
|
731
|
+
hover:bg-red-50 hover:border-red-300 hover:text-red-500
|
|
732
|
+
transition-all"
|
|
733
|
+
>
|
|
734
|
+
<i class="pi pi-minus text-xs"></i>
|
|
735
|
+
</button>
|
|
736
|
+
</div>
|
|
737
|
+
|
|
738
|
+
<!-- Nút thêm -->
|
|
739
|
+
<button
|
|
740
|
+
type="button"
|
|
741
|
+
(click)="addItem()"
|
|
742
|
+
class="flex items-center gap-2 px-4 py-2 w-fit
|
|
743
|
+
rounded-lg border border-dashed border-black/20
|
|
744
|
+
text-sm text-gray-400 font-medium
|
|
745
|
+
hover:border-black/40 hover:text-black
|
|
746
|
+
transition-all dark:border-white/20
|
|
747
|
+
dark:hover:border-white/50 dark:hover:text-white"
|
|
748
|
+
>
|
|
749
|
+
<i class="pi pi-plus text-xs"></i>
|
|
750
|
+
Thêm dòng
|
|
751
|
+
</button>
|
|
752
|
+
</div>
|
|
753
|
+
</div>
|
|
754
|
+
<div class="purchase-card">
|
|
755
|
+
<div class="purchase-header">
|
|
756
|
+
<span class="purchase-num">3</span>
|
|
757
|
+
<p class="purchase-title">Mô tả ngắn</p>
|
|
758
|
+
</div>
|
|
759
|
+
<div class="flex flex-col gap-3">
|
|
760
|
+
<div *ngFor="let item of items; let i = index; trackBy: trackByIndex" class="flex items-center gap-2">
|
|
761
|
+
<input pInputText [(ngModel)]="items[i]" [name]="'item_' + i" placeholder="Nhập giá trị..." class="flex-1" />
|
|
762
|
+
|
|
763
|
+
<!-- Nút xóa — chỉ hiện khi có hơn 1 ô -->
|
|
764
|
+
<button
|
|
765
|
+
*ngIf="items.length > 1"
|
|
766
|
+
type="button"
|
|
767
|
+
(click)="removeItem(i)"
|
|
768
|
+
class="w-8 h-8 flex items-center justify-center
|
|
769
|
+
rounded-lg border border-black/15 text-gray-400
|
|
770
|
+
hover:bg-red-50 hover:border-red-300 hover:text-red-500
|
|
771
|
+
transition-all"
|
|
772
|
+
>
|
|
773
|
+
<i class="pi pi-minus text-xs"></i>
|
|
774
|
+
</button>
|
|
775
|
+
</div>
|
|
776
|
+
|
|
777
|
+
<!-- Nút thêm -->
|
|
778
|
+
<button
|
|
779
|
+
type="button"
|
|
780
|
+
(click)="addItem()"
|
|
781
|
+
class="flex items-center gap-2 px-4 py-2 w-fit
|
|
782
|
+
rounded-lg border border-dashed border-black/20
|
|
783
|
+
text-sm text-gray-400 font-medium
|
|
784
|
+
hover:border-black/40 hover:text-black
|
|
785
|
+
transition-all dark:border-white/20
|
|
786
|
+
dark:hover:border-white/50 dark:hover:text-white"
|
|
787
|
+
>
|
|
788
|
+
<i class="pi pi-plus text-xs"></i>
|
|
789
|
+
Thêm dòng
|
|
790
|
+
</button>
|
|
791
|
+
</div>
|
|
792
|
+
</div>
|
|
793
|
+
<div class="purchase-card">
|
|
794
|
+
<div class="purchase-header">
|
|
795
|
+
<span class="purchase-num">4</span>
|
|
796
|
+
<p class="purchase-title">Hành động đề xuất</p>
|
|
797
|
+
</div>
|
|
798
|
+
<div class="flex flex-col gap-3">
|
|
799
|
+
<div *ngFor="let item of items; let i = index; trackBy: trackByIndex" class="flex items-center gap-2">
|
|
800
|
+
<input pInputText [(ngModel)]="items[i]" [name]="'item_' + i" placeholder="Nhập giá trị..." class="flex-1" />
|
|
801
|
+
|
|
802
|
+
<!-- Nút xóa — chỉ hiện khi có hơn 1 ô -->
|
|
803
|
+
<button
|
|
804
|
+
*ngIf="items.length > 1"
|
|
805
|
+
type="button"
|
|
806
|
+
(click)="removeItem(i)"
|
|
807
|
+
class="w-8 h-8 flex items-center justify-center
|
|
808
|
+
rounded-lg border border-black/15 text-gray-400
|
|
809
|
+
hover:bg-red-50 hover:border-red-300 hover:text-red-500
|
|
810
|
+
transition-all"
|
|
811
|
+
>
|
|
812
|
+
<i class="pi pi-minus text-xs"></i>
|
|
813
|
+
</button>
|
|
814
|
+
</div>
|
|
815
|
+
|
|
816
|
+
<!-- Nút thêm -->
|
|
817
|
+
<button
|
|
818
|
+
type="button"
|
|
819
|
+
(click)="addItem()"
|
|
820
|
+
class="flex items-center gap-2 px-4 py-2 w-fit
|
|
821
|
+
rounded-lg border border-dashed border-black/20
|
|
822
|
+
text-sm text-gray-400 font-medium
|
|
823
|
+
hover:border-black/40 hover:text-black
|
|
824
|
+
transition-all dark:border-white/20
|
|
825
|
+
dark:hover:border-white/50 dark:hover:text-white"
|
|
826
|
+
>
|
|
827
|
+
<i class="pi pi-plus text-xs"></i>
|
|
828
|
+
Thêm dòng
|
|
829
|
+
</button>
|
|
830
|
+
</div>
|
|
831
|
+
</div>
|
|
832
|
+
</div>
|
|
833
|
+
|
|
834
|
+
<!-- Footer -->
|
|
835
|
+
<div class="form-footer">
|
|
836
|
+
<p-button label="Hủy" severity="secondary" outlined />
|
|
837
|
+
<p-button label="Gửi Form" icon="pi pi-send" iconPos="right" (click)="submitForm()" />
|
|
838
|
+
</div>
|
|
839
|
+
</div>
|
|
840
|
+
</div>
|
|
841
|
+
`
|
|
842
|
+
})
|
|
843
|
+
export class MediaDemo implements OnInit {
|
|
844
|
+
cities: City[] = [];
|
|
845
|
+
productCode: Code[] = [];
|
|
846
|
+
supplier: any[] = [];
|
|
847
|
+
selected: string[] = [];
|
|
848
|
+
items: string[] = [''];
|
|
849
|
+
form = {
|
|
850
|
+
nguoiLap: '',
|
|
851
|
+
nhom: '',
|
|
852
|
+
viTri: '',
|
|
853
|
+
nhaCungCap: '',
|
|
854
|
+
maHang: '',
|
|
855
|
+
ngayPhatSinh: null,
|
|
856
|
+
tenLoi: '',
|
|
857
|
+
boPhan: '',
|
|
858
|
+
moTa: ''
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
purchaseGroups = [
|
|
862
|
+
{
|
|
863
|
+
num: 1,
|
|
864
|
+
title: 'Yêu cầu mua hàng',
|
|
865
|
+
items: [
|
|
866
|
+
{ id: 'y1', value: 'ban-ve', label: 'Bản vẽ/thông số không rõ ràng' },
|
|
867
|
+
{ id: 'y2', value: 'tieu-chuan', label: 'Thiếu tiêu chuẩn kiểm tra' },
|
|
868
|
+
{ id: 'y3', value: 'sai-ma', label: 'Sai mã / tên sản phẩm' }
|
|
869
|
+
]
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
num: 2,
|
|
873
|
+
title: 'Lập PR / Duyệt PR',
|
|
874
|
+
items: [
|
|
875
|
+
{ id: 'p1', value: 'pr-trung', label: 'PR tạo trùng' },
|
|
876
|
+
{ id: 'p2', value: 'pr-thieu', label: 'Thiếu thông tin PR' },
|
|
877
|
+
{ id: 'p3', value: 'pr-sai-gia', label: 'Sai đơn giá trên PR' }
|
|
878
|
+
]
|
|
879
|
+
},
|
|
880
|
+
{
|
|
881
|
+
num: 3,
|
|
882
|
+
title: 'Tìm kiếm NCC',
|
|
883
|
+
items: [
|
|
884
|
+
{ id: 'n1', value: 'ncc-nang-luc', label: 'NCC không đủ năng lực' },
|
|
885
|
+
{ id: 'n2', value: 'ncc-audit', label: 'NCC chưa được audit' },
|
|
886
|
+
{ id: 'n3', value: 'ncc-iso', label: 'NCC không có ISO/IATF' }
|
|
887
|
+
]
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
num: 4,
|
|
891
|
+
title: 'So sánh giá',
|
|
892
|
+
items: [
|
|
893
|
+
{ id: 'g1', value: 'bao-gia', label: 'Báo giá không rõ điều kiện' },
|
|
894
|
+
{ id: 'g2', value: 'sai-gia', label: 'Sai giá khi lên PO' },
|
|
895
|
+
{ id: 'g3', value: 'gia-cu', label: 'Không cập nhật giá mới' },
|
|
896
|
+
{ id: 'g4', value: 'phi-phat-sinh', label: 'Giá chưa bao gồm chi phí PS' }
|
|
897
|
+
]
|
|
898
|
+
},
|
|
899
|
+
{
|
|
900
|
+
num: 5,
|
|
901
|
+
title: 'Lập PO / Duyệt PO',
|
|
902
|
+
items: [
|
|
903
|
+
{ id: 'po1', value: 'po-sai-don-gia', label: 'Sai đơn giá trên PO' },
|
|
904
|
+
{ id: 'po2', value: 'po-thieu-tt', label: 'Thiếu thông tin PO' },
|
|
905
|
+
{ id: 'po3', value: 'po-trung', label: 'PO tạo trùng' },
|
|
906
|
+
{ id: 'po4', value: 'po-sai-ncc', label: 'Sai thông tin NCC' }
|
|
907
|
+
]
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
num: 6,
|
|
911
|
+
title: 'Thực hiện mua hàng',
|
|
912
|
+
items: [
|
|
913
|
+
{ id: 'th1', value: 'th-tre-han', label: 'Trễ hạn giao hàng' },
|
|
914
|
+
{ id: 'th2', value: 'th-sai-sl', label: 'Sai số lượng đặt hàng' },
|
|
915
|
+
{ id: 'th3', value: 'th-khong-xn', label: 'Không xác nhận đơn hàng' },
|
|
916
|
+
{ id: 'th4', value: 'th-sai-dc', label: 'Sai địa chỉ giao hàng' }
|
|
917
|
+
]
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
num: 7,
|
|
921
|
+
title: 'Nhận hàng',
|
|
922
|
+
items: [
|
|
923
|
+
{ id: 'nh1', value: 'nh-thieu', label: 'Thiếu hàng so với PO' },
|
|
924
|
+
{ id: 'nh2', value: 'nh-hong', label: 'Hàng hỏng khi nhận' },
|
|
925
|
+
{ id: 'nh3', value: 'nh-sai-qc', label: 'Không kiểm tra QC đầu vào' },
|
|
926
|
+
{ id: 'nh4', value: 'nh-sai-ma', label: 'Sai mã hàng nhận về' }
|
|
927
|
+
]
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
num: 8,
|
|
931
|
+
title: 'Thanh toán',
|
|
932
|
+
items: [
|
|
933
|
+
{ id: 'tt1', value: 'tt-sai-so', label: 'Sai số tiền thanh toán' },
|
|
934
|
+
{ id: 'tt2', value: 'tt-tre', label: 'Thanh toán trễ hạn' },
|
|
935
|
+
{ id: 'tt3', value: 'tt-thieu-hs', label: 'Thiếu hồ sơ thanh toán' },
|
|
936
|
+
{ id: 'tt4', value: 'tt-sai-tk', label: 'Sai tài khoản thụ hưởng' }
|
|
937
|
+
]
|
|
938
|
+
}
|
|
939
|
+
];
|
|
940
|
+
|
|
941
|
+
reason = [
|
|
942
|
+
{
|
|
943
|
+
num: 1,
|
|
944
|
+
title: 'Con người (MAN)'
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
num: 2,
|
|
948
|
+
title: 'Lập PR / Duyệt PR'
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
num: 3,
|
|
952
|
+
title: 'Tìm kiếm NCC'
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
num: 4,
|
|
956
|
+
title: 'So sánh giá'
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
num: 5,
|
|
960
|
+
title: 'Lập PO / Duyệt PO'
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
num: 6,
|
|
964
|
+
title: 'Thực hiện mua hàng'
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
num: 7,
|
|
968
|
+
title: 'Nhận hàng'
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
num: 8,
|
|
972
|
+
title: 'Thanh toán'
|
|
973
|
+
}
|
|
974
|
+
];
|
|
975
|
+
|
|
976
|
+
option = [
|
|
977
|
+
{
|
|
978
|
+
name: 'Hoàn thành',
|
|
979
|
+
value: 1
|
|
980
|
+
},
|
|
981
|
+
{
|
|
982
|
+
name: 'Chưa hoàn thành',
|
|
983
|
+
value: 2
|
|
984
|
+
}
|
|
985
|
+
];
|
|
986
|
+
|
|
987
|
+
ngOnInit() {
|
|
988
|
+
this.cities = [
|
|
989
|
+
{ name: 'Vật tư', code: 'VT' },
|
|
990
|
+
{ name: 'Nguyên liệu', code: 'NL' },
|
|
991
|
+
{ name: 'Dịch vụ', code: 'DV' },
|
|
992
|
+
{ name: 'Thiết bị', code: 'TB' }
|
|
993
|
+
];
|
|
994
|
+
this.productCode = [
|
|
995
|
+
{ name: 'MH001', code: '1' },
|
|
996
|
+
{ name: 'MH002', code: '2' },
|
|
997
|
+
{ name: 'MH003', code: '3' }
|
|
998
|
+
];
|
|
999
|
+
this.supplier = [
|
|
1000
|
+
{ name: 'NCC An Vũ', code: 'AV' },
|
|
1001
|
+
{ name: 'NCC Nông Lâm', code: 'NL' },
|
|
1002
|
+
{ name: 'Yamaichi VN', code: 'YM' }
|
|
1003
|
+
];
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
submitForm() {
|
|
1007
|
+
console.log({ form: this.form, selected: this.selected });
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
addItem() {
|
|
1011
|
+
this.items.push('');
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
removeItem(index: number) {
|
|
1015
|
+
this.items.splice(index, 1);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
trackByIndex(index: number) {
|
|
1019
|
+
return index;
|
|
1020
|
+
}
|
|
1021
|
+
}
|