Просмотр исходного кода

[add]

檀家情報の編集画面を作成
IDごとに編集機能
poohr 1 месяц назад
Родитель
Сommit
641b399d29

+ 137
- 0
src/app/pages/danka-edit/danka-edit.html Просмотреть файл

@@ -0,0 +1,137 @@
1
+<app-header></app-header>
2
+
3
+<div class="breadcrumb">
4
+  ホーム &gt; 檀家(世帯) &gt; 編集
5
+</div>
6
+
7
+<div class="danka-edit-page">
8
+  <app-side-menu></app-side-menu>
9
+
10
+  <main class="danka-edit-main">
11
+    <section class="edit-panel">
12
+      <div class="page-title-area">
13
+        <h1>檀家(世帯)編集</h1>
14
+      </div>
15
+
16
+      <form [formGroup]="dankaForm" class="edit-form">
17
+        <div class="edit-content">
18
+          <section class="basic-edit-section">
19
+            <h2>基本情報</h2>
20
+
21
+            <div class="form-list">
22
+              <div class="form-row">
23
+                <label for="householdName">世帯名</label>
24
+                <input
25
+                  id="householdName"
26
+                  type="text"
27
+                  formControlName="householdName"
28
+                />
29
+              </div>
30
+
31
+              <div class="form-row">
32
+                <label for="householder">世帯主</label>
33
+                <input
34
+                  id="householder"
35
+                  type="text"
36
+                  formControlName="householder"
37
+                />
38
+              </div>
39
+
40
+              <div class="form-row">
41
+                <label for="postalCode">郵便番号</label>
42
+                <input
43
+                  id="postalCode"
44
+                  type="text"
45
+                  formControlName="postalCode"
46
+                />
47
+              </div>
48
+
49
+              <div class="form-row">
50
+                <label for="address">住所</label>
51
+                <input
52
+                  id="address"
53
+                  type="text"
54
+                  formControlName="address"
55
+                />
56
+              </div>
57
+            </div>
58
+          </section>
59
+
60
+          <section class="phone-edit-section">
61
+            <div class="section-heading">
62
+              <h2>電話番号(複数登録)</h2>
63
+              <p>番号と備考を複数登録できます。</p>
64
+            </div>
65
+
66
+            <div formArrayName="phones" class="phone-table">
67
+              <div class="phone-table-header">
68
+                <div>番号</div>
69
+                <div>備考</div>
70
+                <div>操作</div>
71
+              </div>
72
+
73
+              @for (phone of phones.controls; track $index; let i = $index) {
74
+                <div class="phone-table-row" [formGroupName]="i">
75
+                  <div>
76
+                    <input
77
+                      type="text"
78
+                      formControlName="tel"
79
+                      placeholder="電話番号"
80
+                    />
81
+                  </div>
82
+
83
+                  <div>
84
+                    <input
85
+                      type="text"
86
+                      formControlName="note"
87
+                      placeholder="備考"
88
+                    />
89
+                  </div>
90
+
91
+                  <div class="phone-row-action">
92
+                    <button
93
+                      type="button"
94
+                      class="remove-phone-button"
95
+                      (click)="removePhone(i)"
96
+                    >
97
+                      削除
98
+                    </button>
99
+                  </div>
100
+                </div>
101
+              }
102
+            </div>
103
+
104
+            <div class="phone-action">
105
+              <button
106
+                type="button"
107
+                class="add-phone-button"
108
+                (click)="addPhone()"
109
+              >
110
+                電話を追加
111
+              </button>
112
+            </div>
113
+          </section>
114
+        </div>
115
+
116
+        <div class="bottom-actions">
117
+          <button type="button" class="delete-button">
118
+            削除
119
+          </button>
120
+
121
+          <button type="button" class="cancel-button">
122
+            キャンセル
123
+          </button>
124
+
125
+          <button
126
+            type="button"
127
+            class="save-button"
128
+            (click)="saveDanka()"
129
+          >
130
+            保存
131
+          </button>
132
+        </div>
133
+      </form>
134
+    </section>
135
+  </main>
136
+</div>
137
+

+ 313
- 0
src/app/pages/danka-edit/danka-edit.scss Просмотреть файл

@@ -0,0 +1,313 @@
1
+:host {
2
+  position: relative;
3
+  display: block;
4
+  min-height: 100vh;
5
+  background: #f4eee4;
6
+  color: #2f2720;
7
+}
8
+
9
+.breadcrumb {
10
+  position: absolute;
11
+  top: 28px;
12
+  left: 50%;
13
+  transform: translateX(-50%);
14
+  color: #7b6b5c;
15
+  font-size: 14px;
16
+  z-index: 2;
17
+}
18
+
19
+.danka-edit-page {
20
+  display: flex;
21
+  align-items: flex-start;
22
+  gap: 8px;
23
+  background: #f4eee4;
24
+}
25
+
26
+.danka-edit-main {
27
+  flex: 1;
28
+  padding-right: 34px;
29
+  box-sizing: border-box;
30
+}
31
+
32
+.edit-panel {
33
+  min-height: 650px;
34
+  padding: 26px 34px 36px;
35
+  background: #ffffff;
36
+  border: 2px solid #d8caba;
37
+  border-radius: 76px;
38
+  box-sizing: border-box;
39
+}
40
+
41
+.page-title-area {
42
+  margin-bottom: 8px;
43
+}
44
+
45
+.page-title-area h1 {
46
+  margin: 0;
47
+  color: #2f2720;
48
+  font-size: 32px;
49
+  line-height: 1.2;
50
+  font-weight: 800;
51
+  letter-spacing: 0.02em;
52
+}
53
+
54
+.edit-form {
55
+  display: block;
56
+  width: 100%;
57
+  margin: 0;
58
+  color: #2f2720;
59
+}
60
+
61
+.edit-form input,
62
+.edit-form button {
63
+  font-family: inherit;
64
+}
65
+
66
+.edit-content {
67
+  display: grid;
68
+  grid-template-columns: minmax(0, 1fr) 520px;
69
+  gap: 48px;
70
+  align-items: start;
71
+}
72
+
73
+.basic-edit-section,
74
+.phone-edit-section {
75
+  padding-top: 4px;
76
+}
77
+
78
+.basic-edit-section h2,
79
+.phone-edit-section h2,
80
+.support-box h2 {
81
+  margin: 0;
82
+  color: #2f2720;
83
+  font-size: 22px;
84
+  font-weight: 800;
85
+}
86
+
87
+.section-heading p {
88
+  margin: 6px 0 14px;
89
+  color: #7b6b5c;
90
+  font-size: 15px;
91
+}
92
+
93
+/* 基本情報 */
94
+.form-list {
95
+  margin-top: 14px;
96
+}
97
+
98
+.form-row {
99
+  display: grid;
100
+  grid-template-columns: 120px 1fr;
101
+  align-items: center;
102
+  gap: 16px;
103
+  margin-bottom: 14px;
104
+}
105
+
106
+.form-row label {
107
+  color: #4b3c31;
108
+  font-size: 17px;
109
+  font-weight: 800;
110
+}
111
+
112
+.form-row input {
113
+  width: 100%;
114
+  height: 54px;
115
+  padding: 0 14px;
116
+  border: 2px solid #d8caba;
117
+  border-radius: 8px;
118
+  background: #fffdf9;
119
+  color: #2f2720;
120
+  font-size: 18px;
121
+  font-weight: 600;
122
+  box-sizing: border-box;
123
+  outline: none;
124
+}
125
+
126
+.form-row input:focus {
127
+  border-color: #8a6543;
128
+  box-shadow: 0 0 0 3px rgba(138, 101, 67, 0.15);
129
+}
130
+
131
+/* 電話番号 */
132
+.phone-table {
133
+  width: 100%;
134
+}
135
+
136
+.phone-table-header,
137
+.phone-table-row {
138
+  display: grid;
139
+  grid-template-columns: 1.35fr 1.45fr 84px;
140
+  align-items: center;
141
+  column-gap: 10px;
142
+}
143
+
144
+.phone-table-header {
145
+  min-height: 38px;
146
+  padding: 0 10px;
147
+  border: 2px solid #d8caba;
148
+  border-radius: 6px;
149
+  background: #eadfce;
150
+  color: #5a4a3c;
151
+  font-size: 15px;
152
+  font-weight: 800;
153
+  box-sizing: border-box;
154
+}
155
+
156
+.phone-table-row {
157
+  min-height: 56px;
158
+  margin-top: 4px;
159
+  padding: 6px 10px;
160
+  border: 2px solid #d8caba;
161
+  border-radius: 8px;
162
+  background: #fffdf9;
163
+  color: #2f2720;
164
+  font-size: 16px;
165
+  box-sizing: border-box;
166
+}
167
+
168
+.phone-table-row > div {
169
+  display: flex;
170
+  align-items: center;
171
+}
172
+
173
+.phone-table-row input {
174
+  width: 100%;
175
+  height: 38px;
176
+  padding: 0 10px;
177
+  border: none;
178
+  border-radius: 6px;
179
+  background: transparent;
180
+  color: #2f2720;
181
+  font-size: 16px;
182
+  font-weight: 600;
183
+  box-sizing: border-box;
184
+  outline: none;
185
+}
186
+
187
+.phone-table-row input:focus {
188
+  background: #ffffff;
189
+  box-shadow: inset 0 0 0 2px #8a6543;
190
+}
191
+
192
+.phone-table-row input::placeholder {
193
+  color: #9b8b7a;
194
+  font-weight: 500;
195
+}
196
+
197
+.phone-row-action {
198
+  justify-content: flex-end;
199
+}
200
+
201
+.remove-phone-button {
202
+  width: 68px;
203
+  height: 34px;
204
+  border: 2px solid #d8caba;
205
+  border-radius: 6px;
206
+  background: #ffffff;
207
+  color: #6a4a35;
208
+  font-size: 14px;
209
+  font-weight: 800;
210
+  cursor: pointer;
211
+  box-sizing: border-box;
212
+}
213
+
214
+.remove-phone-button:hover {
215
+  background: #f6efe6;
216
+}
217
+
218
+.phone-action {
219
+  display: flex;
220
+  justify-content: flex-end;
221
+  margin-top: 8px;
222
+}
223
+
224
+.add-phone-button {
225
+  width: 170px;
226
+  height: 46px;
227
+  border: 2px solid #d8caba;
228
+  border-radius: 8px;
229
+  background: #ffffff;
230
+  color: #2f2720;
231
+  font-size: 16px;
232
+  font-weight: 800;
233
+  cursor: pointer;
234
+  box-sizing: border-box;
235
+}
236
+
237
+.add-phone-button:hover {
238
+  background: #f6efe6;
239
+}
240
+
241
+/* 入力補助 */
242
+.support-box {
243
+  min-height: 142px;
244
+  margin-top: 56px;
245
+  padding: 28px 30px;
246
+  border: 2px solid #d8caba;
247
+  border-radius: 24px;
248
+  background: #fffdf9;
249
+  box-sizing: border-box;
250
+}
251
+
252
+.support-box ul {
253
+  margin: 12px 0 0;
254
+  padding-left: 22px;
255
+  color: #6f6257;
256
+  font-size: 15px;
257
+  line-height: 1.65;
258
+}
259
+
260
+/* 下部ボタン */
261
+.bottom-actions {
262
+  display: flex;
263
+  justify-content: flex-end;
264
+  align-items: center;
265
+  gap: 12px;
266
+  margin-top: 22px;
267
+}
268
+
269
+.delete-button,
270
+.cancel-button,
271
+.save-button {
272
+  min-width: 116px;
273
+  height: 52px;
274
+  border: 2px solid #d8caba;
275
+  border-radius: 8px;
276
+  font-size: 17px;
277
+  font-weight: 800;
278
+  cursor: pointer;
279
+  box-sizing: border-box;
280
+}
281
+
282
+.delete-button,
283
+.cancel-button {
284
+  background: #ffffff;
285
+  color: #2f2720;
286
+}
287
+
288
+.save-button {
289
+  background: #8a6543;
290
+  border-color: #8a6543;
291
+  color: #ffffff;
292
+}
293
+
294
+.delete-button:hover,
295
+.cancel-button:hover {
296
+  background: #f6efe6;
297
+}
298
+
299
+.save-button:hover {
300
+  background: #765639;
301
+}
302
+
303
+.bottom-note {
304
+  width: 700px;
305
+  margin: 18px 0 22px 36px;
306
+  padding: 4px 12px;
307
+  border: 2px solid #d8caba;
308
+  border-radius: 4px;
309
+  background: #eadfce;
310
+  color: #7b6b5c;
311
+  font-size: 14px;
312
+  box-sizing: border-box;
313
+}

+ 22
- 0
src/app/pages/danka-edit/danka-edit.spec.ts Просмотреть файл

@@ -0,0 +1,22 @@
1
+import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+import { DankaEdit } from './danka-edit';
4
+
5
+describe('DankaEdit', () => {
6
+  let component: DankaEdit;
7
+  let fixture: ComponentFixture<DankaEdit>;
8
+
9
+  beforeEach(async () => {
10
+    await TestBed.configureTestingModule({
11
+      imports: [DankaEdit],
12
+    }).compileComponents();
13
+
14
+    fixture = TestBed.createComponent(DankaEdit);
15
+    component = fixture.componentInstance;
16
+    await fixture.whenStable();
17
+  });
18
+
19
+  it('should create', () => {
20
+    expect(component).toBeTruthy();
21
+  });
22
+});

+ 72
- 0
src/app/pages/danka-edit/danka-edit.ts Просмотреть файл

@@ -0,0 +1,72 @@
1
+import { Component, inject } from '@angular/core';
2
+import {
3
+  FormBuilder,
4
+  FormGroup,
5
+  FormControl,
6
+  FormArray,
7
+  ReactiveFormsModule,
8
+  Validators,
9
+} from '@angular/forms';
10
+import { AppHeader } from '../../share/header/app-header';
11
+import { AppSideMenu } from '../../share/side-menu/app-side-menu';
12
+import { DankaService } from '../../services/dankaService';
13
+
14
+@Component({
15
+  selector: 'app-danka-edit',
16
+  imports: [AppHeader, AppSideMenu, ReactiveFormsModule],
17
+  templateUrl: './danka-edit.html',
18
+  styleUrl: './danka-edit.scss',
19
+})
20
+export class DankaEdit {
21
+  private dankaService = inject(DankaService);
22
+
23
+  dankaForm = new FormGroup({
24
+    householdName: new FormControl('鈴木家'),
25
+    householder: new FormControl('鈴木 太郎'),
26
+    postalCode: new FormControl('123-4567'),
27
+    address: new FormControl('市内 1-2-3'),
28
+    phones: new FormArray([
29
+      this.createPhoneForm('03-xxxx-xxxx', '自宅'),
30
+      this.createPhoneForm('090-xxxx-xxxx', '世帯主'),
31
+      this.createPhoneForm('0584-xx-xxxx', '寺報連絡'),
32
+    ]),
33
+  });
34
+
35
+  get phones() {
36
+    return this.dankaForm.get('phones') as FormArray;
37
+  }
38
+
39
+  createPhoneForm(string = '', note = '') {
40
+    return new FormGroup({
41
+      tel: new FormControl(string),
42
+      note: new FormControl(note),
43
+    });
44
+  }
45
+
46
+  addPhone() {
47
+    this.phones.push(this.createPhoneForm());
48
+  }
49
+
50
+  removePhone(index: number) {
51
+    this.phones.removeAt(index);
52
+  }
53
+
54
+  saveDanka() {
55
+    const formValue = this.dankaForm.value;
56
+
57
+    const updatedDanka = {
58
+      id: '1',
59
+      householdName: formValue.householdName ?? '',
60
+      householder: formValue.householder ?? '',
61
+      postalCode: formValue.postalCode ?? '',
62
+      address: formValue.address ?? '',
63
+      phones: (formValue.phones ?? []).map((phone) => ({
64
+        tel: phone.tel ?? '',
65
+        note: phone.note ?? '',
66
+      })),
67
+    };
68
+
69
+    this.dankaService.saveDanka(updatedDanka);
70
+    console.log(this.dankaService.getDankaList());
71
+  }
72
+}

Загрузка…
Отмена
Сохранить