@dssp/dkpi 1.0.0-alpha.36 → 1.0.0-alpha.37

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.
@@ -0,0 +1,18 @@
1
+ import '@material/web/button/outlined-button.js';
2
+ import '@material/web/icon/icon.js';
3
+ import { LitElement } from 'lit';
4
+ export declare class PagenationControl extends LitElement {
5
+ static styles: import("lit").CSSResult[];
6
+ currentPage: number;
7
+ totalItems: number;
8
+ pageLimit: number;
9
+ private get totalPages();
10
+ private get pageBlock();
11
+ render(): import("lit-html").TemplateResult<1>;
12
+ private _emitPageChange;
13
+ private _numberButtons;
14
+ private _onFirst;
15
+ private _onPrev;
16
+ private _onNext;
17
+ private _onLast;
18
+ }
@@ -0,0 +1,142 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import '@material/web/button/outlined-button.js';
3
+ import '@material/web/icon/icon.js';
4
+ import { css, html, LitElement } from 'lit';
5
+ import { customElement, property } from 'lit/decorators.js';
6
+ let PagenationControl = class PagenationControl extends LitElement {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.currentPage = 1;
10
+ this.totalItems = 0;
11
+ this.pageLimit = 20;
12
+ }
13
+ get totalPages() {
14
+ const totalPages = Math.ceil((this.totalItems || 0) / (this.pageLimit || 1));
15
+ return Math.max(1, totalPages);
16
+ }
17
+ get pageBlock() {
18
+ const blockSize = 10;
19
+ const blockIndex = Math.floor((this.currentPage - 1) / blockSize);
20
+ const start = blockIndex * blockSize + 1;
21
+ const end = Math.min(start + blockSize - 1, this.totalPages);
22
+ return { start, end };
23
+ }
24
+ render() {
25
+ return html `
26
+ <div pagination>
27
+ <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onFirst}>
28
+ <md-icon>first_page</md-icon>
29
+ </md-outlined-button>
30
+ <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onPrev}>
31
+ <md-icon>chevron_left</md-icon>
32
+ </md-outlined-button>
33
+
34
+ <div numbers>${this._numberButtons()}</div>
35
+
36
+ <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onNext}>
37
+ <md-icon>chevron_right</md-icon>
38
+ </md-outlined-button>
39
+ <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onLast}>
40
+ <md-icon>last_page</md-icon>
41
+ </md-outlined-button>
42
+ </div>
43
+ `;
44
+ }
45
+ _emitPageChange(nextPage) {
46
+ const bounded = Math.min(Math.max(1, nextPage), this.totalPages);
47
+ if (bounded !== this.currentPage) {
48
+ this.dispatchEvent(new CustomEvent('page-change', {
49
+ detail: { page: bounded },
50
+ bubbles: true,
51
+ composed: true
52
+ }));
53
+ }
54
+ }
55
+ _numberButtons() {
56
+ const { start, end } = this.pageBlock;
57
+ const buttons = [];
58
+ for (let page = start; page <= end; page++) {
59
+ const selected = page === this.currentPage;
60
+ buttons.push(html `<md-outlined-button data-page ?selected=${selected} @click=${() => this._emitPageChange(page)}
61
+ >${page}</md-outlined-button
62
+ >`);
63
+ }
64
+ return buttons;
65
+ }
66
+ _onFirst() {
67
+ this._emitPageChange(1);
68
+ }
69
+ _onPrev() {
70
+ this._emitPageChange(this.currentPage - 1);
71
+ }
72
+ _onNext() {
73
+ this._emitPageChange(this.currentPage + 1);
74
+ }
75
+ _onLast() {
76
+ this._emitPageChange(this.totalPages);
77
+ }
78
+ };
79
+ PagenationControl.styles = [
80
+ css `
81
+ div[pagination] {
82
+ display: flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ gap: var(--spacing-medium, 8px);
86
+ margin: var(--spacing-large, 12px);
87
+
88
+ div[numbers] {
89
+ display: inline-flex;
90
+ gap: var(--spacing-tiny, 2px);
91
+ }
92
+
93
+ md-icon {
94
+ --md-icon-size: 18px;
95
+ }
96
+
97
+ md-outlined-button {
98
+ --md-outlined-button-container-height: 30px;
99
+ --md-outlined-button-label-text-size: 13px;
100
+ padding: 0 10px;
101
+ }
102
+
103
+ md-outlined-button[selected] {
104
+ --md-outlined-button-label-text-color: #ffffff;
105
+ --md-sys-color-outline: #0595e5;
106
+ background-color: #0595e5;
107
+ }
108
+
109
+ md-outlined-button[icon] {
110
+ min-width: 30px;
111
+ width: 30px;
112
+ padding: 0;
113
+ }
114
+
115
+ md-outlined-button[icon] md-icon {
116
+ margin-top: 5px;
117
+ }
118
+
119
+ md-outlined-button[data-page] {
120
+ min-width: 34px;
121
+ padding: 0 8px;
122
+ }
123
+ }
124
+ `
125
+ ];
126
+ __decorate([
127
+ property({ type: Number }),
128
+ __metadata("design:type", Number)
129
+ ], PagenationControl.prototype, "currentPage", void 0);
130
+ __decorate([
131
+ property({ type: Number }),
132
+ __metadata("design:type", Number)
133
+ ], PagenationControl.prototype, "totalItems", void 0);
134
+ __decorate([
135
+ property({ type: Number }),
136
+ __metadata("design:type", Number)
137
+ ], PagenationControl.prototype, "pageLimit", void 0);
138
+ PagenationControl = __decorate([
139
+ customElement('pagenation-control')
140
+ ], PagenationControl);
141
+ export { PagenationControl };
142
+ //# sourceMappingURL=pagenation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagenation.js","sourceRoot":"","sources":["../../client/components/pagenation.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/outlined-button.js'\nimport '@material/web/icon/icon.js'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('pagenation-control')\nexport class PagenationControl extends LitElement {\n static styles = [\n css`\n div[pagination] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-medium, 8px);\n margin: var(--spacing-large, 12px);\n\n div[numbers] {\n display: inline-flex;\n gap: var(--spacing-tiny, 2px);\n }\n\n md-icon {\n --md-icon-size: 18px;\n }\n\n md-outlined-button {\n --md-outlined-button-container-height: 30px;\n --md-outlined-button-label-text-size: 13px;\n padding: 0 10px;\n }\n\n md-outlined-button[selected] {\n --md-outlined-button-label-text-color: #ffffff;\n --md-sys-color-outline: #0595e5;\n background-color: #0595e5;\n }\n\n md-outlined-button[icon] {\n min-width: 30px;\n width: 30px;\n padding: 0;\n }\n\n md-outlined-button[icon] md-icon {\n margin-top: 5px;\n }\n\n md-outlined-button[data-page] {\n min-width: 34px;\n padding: 0 8px;\n }\n }\n `\n ]\n\n @property({ type: Number }) currentPage: number = 1\n @property({ type: Number }) totalItems: number = 0\n @property({ type: Number }) pageLimit: number = 20\n\n private get totalPages(): number {\n const totalPages = Math.ceil((this.totalItems || 0) / (this.pageLimit || 1))\n return Math.max(1, totalPages)\n }\n\n private get pageBlock(): { start: number; end: number } {\n const blockSize = 10\n const blockIndex = Math.floor((this.currentPage - 1) / blockSize)\n const start = blockIndex * blockSize + 1\n const end = Math.min(start + blockSize - 1, this.totalPages)\n return { start, end }\n }\n\n render() {\n return html`\n <div pagination>\n <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onFirst}>\n <md-icon>first_page</md-icon>\n </md-outlined-button>\n <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onPrev}>\n <md-icon>chevron_left</md-icon>\n </md-outlined-button>\n\n <div numbers>${this._numberButtons()}</div>\n\n <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onNext}>\n <md-icon>chevron_right</md-icon>\n </md-outlined-button>\n <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onLast}>\n <md-icon>last_page</md-icon>\n </md-outlined-button>\n </div>\n `\n }\n\n private _emitPageChange(nextPage: number) {\n const bounded = Math.min(Math.max(1, nextPage), this.totalPages)\n if (bounded !== this.currentPage) {\n this.dispatchEvent(\n new CustomEvent('page-change', {\n detail: { page: bounded },\n bubbles: true,\n composed: true\n })\n )\n }\n }\n\n private _numberButtons() {\n const { start, end } = this.pageBlock\n const buttons = [] as any[]\n for (let page = start; page <= end; page++) {\n const selected = page === this.currentPage\n buttons.push(\n html`<md-outlined-button data-page ?selected=${selected} @click=${() => this._emitPageChange(page)}\n >${page}</md-outlined-button\n >`\n )\n }\n return buttons\n }\n\n private _onFirst() {\n this._emitPageChange(1)\n }\n\n private _onPrev() {\n this._emitPageChange(this.currentPage - 1)\n }\n\n private _onNext() {\n this._emitPageChange(this.currentPage + 1)\n }\n\n private _onLast() {\n this._emitPageChange(this.totalPages)\n }\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import '@material/web/icon/icon.js';
2
2
  import { PageView } from '@operato/shell';
3
+ import '../components/pagenation';
3
4
  declare const SvProjectCompletedListPage_base: typeof PageView & import("@open-wc/dedupe-mixin").Constructor<import("@open-wc/scoped-elements/types/src/types").ScopedElementsHost>;
4
5
  export declare class SvProjectCompletedListPage extends SvProjectCompletedListPage_base {
5
6
  static styles: import("lit").CSSResult[];
@@ -9,10 +10,14 @@ export declare class SvProjectCompletedListPage extends SvProjectCompletedListPa
9
10
  private projectName;
10
11
  private projectList;
11
12
  private projectCount;
13
+ private currentPage;
14
+ private readonly pageLimit;
15
+ get totalPages(): number;
12
16
  render(): import("lit-html").TemplateResult<1>;
13
17
  pageUpdated(changes: any, lifecycle: any): Promise<void>;
14
18
  getProjectList(): Promise<void>;
15
19
  private _onInputChange;
16
20
  private _onKeypress;
21
+ private _changePage;
17
22
  }
18
23
  export {};
@@ -7,18 +7,24 @@ import { ScopedElementsMixin } from '@open-wc/scoped-elements';
7
7
  import { client } from '@operato/graphql';
8
8
  import gql from 'graphql-tag';
9
9
  import { ProjectState } from './sv-project-list';
10
+ import '../components/pagenation';
10
11
  let SvProjectCompletedListPage = class SvProjectCompletedListPage extends ScopedElementsMixin(PageView) {
11
12
  constructor() {
12
13
  super(...arguments);
13
14
  this.projectName = '';
14
15
  this.projectList = [];
15
16
  this.projectCount = 0;
17
+ this.currentPage = 1;
18
+ this.pageLimit = 20;
16
19
  }
17
20
  get context() {
18
21
  return {
19
22
  title: '완료 프로젝트'
20
23
  };
21
24
  }
25
+ get totalPages() {
26
+ return Math.max(1, Math.ceil((this.projectCount || 0) / this.pageLimit));
27
+ }
22
28
  render() {
23
29
  var _a;
24
30
  return html `
@@ -74,6 +80,12 @@ let SvProjectCompletedListPage = class SvProjectCompletedListPage extends Scoped
74
80
  `;
75
81
  })}
76
82
  </div>
83
+ <pagenation-control
84
+ .currentPage=${this.currentPage}
85
+ .totalItems=${this.projectCount}
86
+ .pageLimit=${this.pageLimit}
87
+ @page-change=${(e) => this._changePage(e.detail.page)}
88
+ ></pagenation-control>
77
89
  `;
78
90
  }
79
91
  async pageUpdated(changes, lifecycle) {
@@ -85,8 +97,8 @@ let SvProjectCompletedListPage = class SvProjectCompletedListPage extends Scoped
85
97
  var _a, _b;
86
98
  const response = await client.query({
87
99
  query: gql `
88
- query Projects($filters: [Filter!]) {
89
- projects(filters: $filters) {
100
+ query Projects($filters: [Filter!], $sortings: [Sorting!], $pagination: Pagination) {
101
+ projects(filters: $filters, sortings: $sortings, pagination: $pagination) {
90
102
  items {
91
103
  id
92
104
  name
@@ -127,7 +139,9 @@ let SvProjectCompletedListPage = class SvProjectCompletedListPage extends Scoped
127
139
  operator: 'eq',
128
140
  value: ProjectState.COMPLETED
129
141
  }
130
- ]
142
+ ],
143
+ sortings: [{ name: 'createdAt', desc: true }],
144
+ pagination: { page: this.currentPage, limit: this.pageLimit }
131
145
  }
132
146
  });
133
147
  this.projectList = ((_a = response.data.projects) === null || _a === void 0 ? void 0 : _a.items) || [];
@@ -137,10 +151,21 @@ let SvProjectCompletedListPage = class SvProjectCompletedListPage extends Scoped
137
151
  _onInputChange(event) {
138
152
  const target = event.target;
139
153
  this[target.name] = target.value;
154
+ if (target.name === 'projectName') {
155
+ this.currentPage = 1;
156
+ }
140
157
  }
141
158
  // 검색창에서 엔터입력시 검색
142
159
  _onKeypress(event) {
143
160
  if (event.code === 'Enter') {
161
+ this.currentPage = 1;
162
+ this.getProjectList();
163
+ }
164
+ }
165
+ _changePage(page) {
166
+ const nextPage = Math.min(Math.max(1, page), this.totalPages);
167
+ if (nextPage !== this.currentPage) {
168
+ this.currentPage = nextPage;
144
169
  this.getProjectList();
145
170
  }
146
171
  }
@@ -286,6 +311,10 @@ __decorate([
286
311
  state(),
287
312
  __metadata("design:type", Number)
288
313
  ], SvProjectCompletedListPage.prototype, "projectCount", void 0);
314
+ __decorate([
315
+ state(),
316
+ __metadata("design:type", Number)
317
+ ], SvProjectCompletedListPage.prototype, "currentPage", void 0);
289
318
  SvProjectCompletedListPage = __decorate([
290
319
  customElement('sv-project-completed-list')
291
320
  ], SvProjectCompletedListPage);
@@ -1 +1 @@
1
- {"version":3,"file":"sv-project-completed-list.js","sourceRoot":"","sources":["../../client/pages/sv-project-completed-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { PageView } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\nimport { Project, ProjectState } from './sv-project-list'\n\n@customElement('sv-project-completed-list')\nexport class SvProjectCompletedListPage extends ScopedElementsMixin(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n\n width: 100%;\n height: 100%;\n background-color: #f7f7f7;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n div[header] {\n display: flex;\n align-items: center;\n background-color: #2ea4df1a;\n border: 1px solid #2ea4df33;\n margin: 15px 23px;\n font-size: 18px;\n padding: 7px;\n border-radius: 5px;\n\n md-filled-text-field[type='search'] {\n margin-left: 5px;\n margin-right: 26px;\n\n --md-filled-text-field-container-shape: 0px;\n --md-sys-color-primary: #006a6a;\n --md-sys-color-surface-container-highest: transparent;\n --md-filled-text-field-label-text-color: #999999;\n --md-filled-text-field-input-text-color: #4e5055;\n }\n\n md-elevated-button[add-project] {\n font-weight: bold;\n font-size: 16px;\n margin-left: 17px;\n padding: 13px 20px;\n\n --md-sys-color-surface-container-low: #24be7b;\n --md-sys-color-primary: #ffffff;\n --md-elevated-button-container-shape: 7px;\n }\n }\n\n div[body] {\n div[project-container] {\n height: 140px;\n margin: 17px 23px;\n background-color: #ffffff;\n border: 1px solid #cccccc80;\n border-radius: 5px;\n\n & > a {\n display: flex;\n width: 100%;\n height: 100%;\n text-decoration: none;\n color: #000;\n }\n\n img[project-img] {\n width: 285px;\n background-color: #cccccc80;\n }\n img[project-img][no-image] {\n object-fit: contain;\n opacity: 0.5;\n }\n\n span[project-info] {\n flex: 0.45;\n padding: 6px 15px;\n font-size: 16px;\n\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n\n div[name] {\n color: #2e79be;\n font-weight: bold;\n font-size: 19px;\n margin-bottom: 2px;\n }\n }\n\n span[project-state] {\n flex: 0.55;\n padding: 10px 20px;\n\n & > div {\n margin-bottom: 3px;\n }\n\n div[progress] {\n position: relative;\n\n md-linear-progress {\n --md-linear-progress-track-height: 18px;\n --md-linear-progress-active-indicator-height: 18px;\n --md-linear-progress-track-shape: 5px;\n --md-sys-color-primary: #1bb40133;\n --md-sys-color-surface-container-highest: #0595e533;\n --md-linear-progress-track-color: #1bb4011a;\n }\n\n span {\n position: absolute;\n top: 0;\n left: 12px;\n font-size: 12px;\n font-weight: bold;\n color: #1bb401;\n\n &:last-child {\n left: unset;\n right: 12px;\n }\n }\n }\n }\n }\n }\n `\n ]\n\n get context() {\n return {\n title: '완료 프로젝트'\n }\n }\n\n @state() private projectName: string = ''\n @state() private projectList: Project[] = []\n @state() private projectCount: number = 0\n\n render() {\n return html`\n <div header>\n <label>프로젝트 이름</label>\n <md-filled-text-field\n name=\"projectName\"\n type=\"search\"\n label=\"프로젝트 이름\"\n .value=${this.projectName}\n @input=${this._onInputChange}\n @keypress=${this._onKeypress}\n >\n <md-icon slot=\"leading-icon\">search</md-icon>\n </md-filled-text-field>\n\n <strong>총 ${this.projectCount}개</strong>\n </div>\n\n <div body>\n ${this.projectList?.map((project: Project) => {\n return html`\n <div project-container>\n <a href=${`kpi-dashboard?projectId=${project.id}`}>\n <img\n ?no-image=${!project.mainPhoto?.fullpath}\n project-img\n src=${project.mainPhoto?.fullpath || '/assets/images/no-image.png'}\n />\n\n <span project-info>\n <div name>${project.name}</div>\n <div content>${project.buildingComplex.address}</div>\n <div content>면적: ${project.buildingComplex?.area?.toLocaleString() || ''}㎡</div>\n <div content>착공~준공: ${project.startDate} ~ ${project.endDate}</div>\n <div content>발주처: <strong>${project.buildingComplex.clientCompany}</strong></div>\n </span>\n\n <span project-state>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.totalProgress || 0}> </md-linear-progress>\n <span>전체</span>\n <span>${project.totalProgress || 0}%</span>\n </div>\n <div>시공사: ${project.buildingComplex.constructionCompany}</div>\n <div>건설구분: ${project.buildingComplex.constructionType}</div>\n <div>세대수: ${project.buildingComplex?.householdCount?.toLocaleString() || ''}세대</div>\n <div>기타: ${project.buildingComplex.etc}</div>\n </span>\n </a>\n </div>\n `\n })}\n </div>\n `\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n this.getProjectList()\n }\n }\n\n async getProjectList() {\n const response = await client.query({\n query: gql`\n query Projects($filters: [Filter!]) {\n projects(filters: $filters) {\n items {\n id\n name\n startDate\n endDate\n mainPhoto {\n fullpath\n }\n totalProgress\n weeklyProgress\n kpi\n inspPassRate\n robotProgressRate\n structuralSafetyRate\n buildingComplex {\n address\n area\n clientCompany\n constructionCompany\n constructionType\n householdCount\n etc\n }\n }\n total\n }\n }\n `,\n variables: {\n filters: [\n {\n name: 'name',\n operator: 'search',\n value: `%${this.projectName}%`\n },\n {\n name: 'state',\n operator: 'eq',\n value: ProjectState.COMPLETED\n }\n ]\n }\n })\n\n this.projectList = response.data.projects?.items || []\n this.projectCount = response.data.projects?.total || 0\n }\n\n // Input 요소의 값이 변경될 때 호출되는 콜백 함수\n private _onInputChange(event: InputEvent) {\n const target = event.target as HTMLInputElement\n this[target.name] = target.value\n }\n\n // 검색창에서 엔터입력시 검색\n private _onKeypress(event: KeyboardEvent) {\n if (event.code === 'Enter') {\n this.getProjectList()\n }\n }\n}\n"]}
1
+ {"version":3,"file":"sv-project-completed-list.js","sourceRoot":"","sources":["../../client/pages/sv-project-completed-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { PageView } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\nimport { Project, ProjectState } from './sv-project-list'\nimport '../components/pagenation'\n\n@customElement('sv-project-completed-list')\nexport class SvProjectCompletedListPage extends ScopedElementsMixin(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n\n width: 100%;\n height: 100%;\n background-color: #f7f7f7;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n div[header] {\n display: flex;\n align-items: center;\n background-color: #2ea4df1a;\n border: 1px solid #2ea4df33;\n margin: 15px 23px;\n font-size: 18px;\n padding: 7px;\n border-radius: 5px;\n\n md-filled-text-field[type='search'] {\n margin-left: 5px;\n margin-right: 26px;\n\n --md-filled-text-field-container-shape: 0px;\n --md-sys-color-primary: #006a6a;\n --md-sys-color-surface-container-highest: transparent;\n --md-filled-text-field-label-text-color: #999999;\n --md-filled-text-field-input-text-color: #4e5055;\n }\n\n md-elevated-button[add-project] {\n font-weight: bold;\n font-size: 16px;\n margin-left: 17px;\n padding: 13px 20px;\n\n --md-sys-color-surface-container-low: #24be7b;\n --md-sys-color-primary: #ffffff;\n --md-elevated-button-container-shape: 7px;\n }\n }\n\n div[body] {\n div[project-container] {\n height: 140px;\n margin: 17px 23px;\n background-color: #ffffff;\n border: 1px solid #cccccc80;\n border-radius: 5px;\n\n & > a {\n display: flex;\n width: 100%;\n height: 100%;\n text-decoration: none;\n color: #000;\n }\n\n img[project-img] {\n width: 285px;\n background-color: #cccccc80;\n }\n img[project-img][no-image] {\n object-fit: contain;\n opacity: 0.5;\n }\n\n span[project-info] {\n flex: 0.45;\n padding: 6px 15px;\n font-size: 16px;\n\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n\n div[name] {\n color: #2e79be;\n font-weight: bold;\n font-size: 19px;\n margin-bottom: 2px;\n }\n }\n\n span[project-state] {\n flex: 0.55;\n padding: 10px 20px;\n\n & > div {\n margin-bottom: 3px;\n }\n\n div[progress] {\n position: relative;\n\n md-linear-progress {\n --md-linear-progress-track-height: 18px;\n --md-linear-progress-active-indicator-height: 18px;\n --md-linear-progress-track-shape: 5px;\n --md-sys-color-primary: #1bb40133;\n --md-sys-color-surface-container-highest: #0595e533;\n --md-linear-progress-track-color: #1bb4011a;\n }\n\n span {\n position: absolute;\n top: 0;\n left: 12px;\n font-size: 12px;\n font-weight: bold;\n color: #1bb401;\n\n &:last-child {\n left: unset;\n right: 12px;\n }\n }\n }\n }\n }\n }\n `\n ]\n\n get context() {\n return {\n title: '완료 프로젝트'\n }\n }\n\n @state() private projectName: string = ''\n @state() private projectList: Project[] = []\n @state() private projectCount: number = 0\n @state() private currentPage: number = 1\n\n private readonly pageLimit: number = 20\n\n get totalPages(): number {\n return Math.max(1, Math.ceil((this.projectCount || 0) / this.pageLimit))\n }\n\n render() {\n return html`\n <div header>\n <label>프로젝트 이름</label>\n <md-filled-text-field\n name=\"projectName\"\n type=\"search\"\n label=\"프로젝트 이름\"\n .value=${this.projectName}\n @input=${this._onInputChange}\n @keypress=${this._onKeypress}\n >\n <md-icon slot=\"leading-icon\">search</md-icon>\n </md-filled-text-field>\n\n <strong>총 ${this.projectCount}개</strong>\n </div>\n\n <div body>\n ${this.projectList?.map((project: Project) => {\n return html`\n <div project-container>\n <a href=${`kpi-dashboard?projectId=${project.id}`}>\n <img\n ?no-image=${!project.mainPhoto?.fullpath}\n project-img\n src=${project.mainPhoto?.fullpath || '/assets/images/no-image.png'}\n />\n\n <span project-info>\n <div name>${project.name}</div>\n <div content>${project.buildingComplex.address}</div>\n <div content>면적: ${project.buildingComplex?.area?.toLocaleString() || ''}㎡</div>\n <div content>착공~준공: ${project.startDate} ~ ${project.endDate}</div>\n <div content>발주처: <strong>${project.buildingComplex.clientCompany}</strong></div>\n </span>\n\n <span project-state>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.totalProgress || 0}> </md-linear-progress>\n <span>전체</span>\n <span>${project.totalProgress || 0}%</span>\n </div>\n <div>시공사: ${project.buildingComplex.constructionCompany}</div>\n <div>건설구분: ${project.buildingComplex.constructionType}</div>\n <div>세대수: ${project.buildingComplex?.householdCount?.toLocaleString() || ''}세대</div>\n <div>기타: ${project.buildingComplex.etc}</div>\n </span>\n </a>\n </div>\n `\n })}\n </div>\n <pagenation-control\n .currentPage=${this.currentPage}\n .totalItems=${this.projectCount}\n .pageLimit=${this.pageLimit}\n @page-change=${(e: CustomEvent) => this._changePage(e.detail.page)}\n ></pagenation-control>\n `\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n this.getProjectList()\n }\n }\n\n async getProjectList() {\n const response = await client.query({\n query: gql`\n query Projects($filters: [Filter!], $sortings: [Sorting!], $pagination: Pagination) {\n projects(filters: $filters, sortings: $sortings, pagination: $pagination) {\n items {\n id\n name\n startDate\n endDate\n mainPhoto {\n fullpath\n }\n totalProgress\n weeklyProgress\n kpi\n inspPassRate\n robotProgressRate\n structuralSafetyRate\n buildingComplex {\n address\n area\n clientCompany\n constructionCompany\n constructionType\n householdCount\n etc\n }\n }\n total\n }\n }\n `,\n variables: {\n filters: [\n {\n name: 'name',\n operator: 'search',\n value: `%${this.projectName}%`\n },\n {\n name: 'state',\n operator: 'eq',\n value: ProjectState.COMPLETED\n }\n ],\n sortings: [{ name: 'createdAt', desc: true }],\n pagination: { page: this.currentPage, limit: this.pageLimit }\n }\n })\n\n this.projectList = response.data.projects?.items || []\n this.projectCount = response.data.projects?.total || 0\n }\n\n // Input 요소의 값이 변경될 때 호출되는 콜백 함수\n private _onInputChange(event: InputEvent) {\n const target = event.target as HTMLInputElement\n this[target.name] = target.value\n if (target.name === 'projectName') {\n this.currentPage = 1\n }\n }\n\n // 검색창에서 엔터입력시 검색\n private _onKeypress(event: KeyboardEvent) {\n if (event.code === 'Enter') {\n this.currentPage = 1\n this.getProjectList()\n }\n }\n\n private _changePage(page: number) {\n const nextPage = Math.min(Math.max(1, page), this.totalPages)\n if (nextPage !== this.currentPage) {\n this.currentPage = nextPage\n this.getProjectList()\n }\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import '@material/web/icon/icon.js';
2
+ import '../components/pagenation';
2
3
  import { PageView } from '@operato/shell';
3
4
  import { Attachment } from '@things-factory/attachment-base';
4
5
  import type { FileUpload } from 'graphql-upload/GraphQLUpload.js';
@@ -135,10 +136,14 @@ export declare class SvProjectListPage extends SvProjectListPage_base {
135
136
  private projectName;
136
137
  private projectList;
137
138
  private projectCount;
139
+ private currentPage;
140
+ private readonly pageLimit;
141
+ get totalPages(): number;
138
142
  render(): import("lit-html").TemplateResult<1>;
139
143
  pageUpdated(changes: any, lifecycle: any): Promise<void>;
140
144
  getProjectList(): Promise<void>;
141
145
  private _onInputChange;
142
146
  private _onKeypress;
147
+ private _changePage;
143
148
  }
144
149
  export {};
@@ -1,5 +1,6 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import '@material/web/icon/icon.js';
3
+ import '../components/pagenation';
3
4
  import { PageView } from '@operato/shell';
4
5
  import { css, html } from 'lit';
5
6
  import { customElement, state } from 'lit/decorators.js';
@@ -40,12 +41,17 @@ let SvProjectListPage = class SvProjectListPage extends ScopedElementsMixin(Page
40
41
  this.projectName = '';
41
42
  this.projectList = [];
42
43
  this.projectCount = 0;
44
+ this.currentPage = 1;
45
+ this.pageLimit = 20;
43
46
  }
44
47
  get context() {
45
48
  return {
46
49
  title: '진행중 프로젝트'
47
50
  };
48
51
  }
52
+ get totalPages() {
53
+ return Math.max(1, Math.ceil((this.projectCount || 0) / this.pageLimit));
54
+ }
49
55
  render() {
50
56
  var _a;
51
57
  return html `
@@ -121,6 +127,12 @@ let SvProjectListPage = class SvProjectListPage extends ScopedElementsMixin(Page
121
127
  `;
122
128
  })}
123
129
  </div>
130
+ <pagenation-control
131
+ .currentPage=${this.currentPage}
132
+ .totalItems=${this.projectCount}
133
+ .pageLimit=${this.pageLimit}
134
+ @page-change=${(e) => this._changePage(e.detail.page)}
135
+ ></pagenation-control>
124
136
  `;
125
137
  }
126
138
  async pageUpdated(changes, lifecycle) {
@@ -132,8 +144,8 @@ let SvProjectListPage = class SvProjectListPage extends ScopedElementsMixin(Page
132
144
  var _a, _b;
133
145
  const response = await client.query({
134
146
  query: gql `
135
- query Projects($filters: [Filter!]) {
136
- projects(filters: $filters) {
147
+ query Projects($filters: [Filter!], $sortings: [Sorting!], $pagination: Pagination) {
148
+ projects(filters: $filters, sortings: $sortings, pagination: $pagination) {
137
149
  items {
138
150
  id
139
151
  name
@@ -171,7 +183,8 @@ let SvProjectListPage = class SvProjectListPage extends ScopedElementsMixin(Page
171
183
  value: ProjectState.ONGOING
172
184
  }
173
185
  ],
174
- sortings: [{ name: 'createdAt', desc: true }]
186
+ sortings: [{ name: 'createdAt', desc: true }],
187
+ pagination: { page: this.currentPage, limit: this.pageLimit }
175
188
  }
176
189
  });
177
190
  this.projectList = ((_a = response.data.projects) === null || _a === void 0 ? void 0 : _a.items) || [];
@@ -181,10 +194,21 @@ let SvProjectListPage = class SvProjectListPage extends ScopedElementsMixin(Page
181
194
  _onInputChange(event) {
182
195
  const target = event.target;
183
196
  this[target.name] = target.value;
197
+ if (target.name === 'projectName') {
198
+ this.currentPage = 1;
199
+ }
184
200
  }
185
201
  // 검색창에서 엔터입력시 검색
186
202
  _onKeypress(event) {
187
203
  if (event.code === 'Enter') {
204
+ this.currentPage = 1;
205
+ this.getProjectList();
206
+ }
207
+ }
208
+ _changePage(page) {
209
+ const nextPage = Math.min(Math.max(1, page), this.totalPages);
210
+ if (nextPage !== this.currentPage) {
211
+ this.currentPage = nextPage;
188
212
  this.getProjectList();
189
213
  }
190
214
  }
@@ -332,6 +356,10 @@ __decorate([
332
356
  state(),
333
357
  __metadata("design:type", Number)
334
358
  ], SvProjectListPage.prototype, "projectCount", void 0);
359
+ __decorate([
360
+ state(),
361
+ __metadata("design:type", Number)
362
+ ], SvProjectListPage.prototype, "currentPage", void 0);
335
363
  SvProjectListPage = __decorate([
336
364
  customElement('sv-project-list')
337
365
  ], SvProjectListPage);
@@ -1 +1 @@
1
- {"version":3,"file":"sv-project-list.js","sourceRoot":"","sources":["../../client/pages/sv-project-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { PageView } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\nimport { Attachment } from '@things-factory/attachment-base'\nimport type { FileUpload } from 'graphql-upload/GraphQLUpload.js'\n\nexport enum ProjectState {\n 'ONGOING' = '10',\n 'COMPLETED' = '20'\n}\nexport enum BuildingInspectionStatus {\n WAIT = 'WAIT',\n OVERALL_WAIT = 'OVERALL_WAIT',\n REQUEST = 'REQUEST',\n OVERALL_REQUEST = 'OVERALL_REQUEST',\n PASS = 'PASS',\n FAIL = 'FAIL'\n}\nexport const BUILDING_INSPECTION_STATUS = {\n [BuildingInspectionStatus.WAIT]: '검측 대기',\n [BuildingInspectionStatus.OVERALL_WAIT]: '검측 대기',\n [BuildingInspectionStatus.REQUEST]: '검측 요청',\n [BuildingInspectionStatus.OVERALL_REQUEST]: '검측 요청',\n [BuildingInspectionStatus.PASS]: '합격',\n [BuildingInspectionStatus.FAIL]: '불합격'\n}\n\nexport enum ProjectType {\n DSSP = 'DSSP',\n DCSP = 'DCSP',\n DKPI = 'DKPI'\n}\n\nexport interface Project {\n id?: string\n name: string\n startDate?: string\n endDate?: string\n mainPhoto?: Attachment\n mainPhotoUpload?: FileUpload\n totalProgress?: number\n weeklyProgress?: number\n kpi?: number\n inspPassRate?: number\n robotProgressRate?: number\n structuralSafetyRate?: number\n robotCount?: number\n scheduleTable?: Attachment\n buildingComplex: BuildingComplex\n projectType?: ProjectType\n}\nexport interface BuildingComplex {\n id?: string\n address?: string\n latitude?: number\n longitude?: number\n area?: number\n constructionCompany?: string\n clientCompany?: string\n designCompany?: string\n supervisoryCompany?: string\n drawing?: Attachment\n drawingUpload?: FileUpload\n constructionType?: string\n constructionCost?: number\n etc?: string\n householdCount?: number\n buildingCount?: number\n notice?: string\n planXScale?: number\n planYScale?: number\n overallConstructorEmails?: string[]\n taskConstructorEmails?: string[]\n overallSupervisoryEmails?: string[]\n taskSupervisoryEmails?: string[]\n buildings?: Building[]\n}\nexport interface Building {\n id?: string\n name: string | undefined\n floorCount: number | undefined\n hasBasement?: boolean\n basementFloorCount?: number\n drawing?: Attachment\n drawingUpload?: FileUpload\n buildingLevels?: BuildingLevel[]\n}\n\nexport interface BuildingLevel {\n id?: string\n floor?: number\n floorDisplayName?: string\n mainDrawing?: Attachment\n mainDrawingImage?: string\n mainDrawingThumbnail?: string\n mainDrawingUpload?: FileUpload\n elevationDrawing?: Attachment\n elevationDrawingThumbnail?: string\n elevationDrawingUpload?: FileUpload\n rebarDistributionDrawing?: Attachment\n rebarDistributionDrawingThumbnail?: string\n rebarDistributionDrawingUpload?: FileUpload\n etcDrawings?: Attachment[]\n etcDrawingsUpload?: FileUpload[]\n building?: Building\n buildingInspections?: BuildingInspection[]\n}\n\nexport interface BuildingInspection {\n id?: string\n attatchments?: Attachment[]\n // buildingInspectionAttachments?: BuildingInspectionAttachment[]\n status?: BuildingInspectionStatus\n requestDate?: Date\n buildingLevel?: BuildingLevel\n checklist?: Checklist\n createdAt?: Date\n updatedAt?: Date\n deletedAt?: Date\n}\n\nexport interface Checklist {\n id: string\n name?: string\n documentNo?: string\n constructionType?: string\n constructionDetailType?: string\n location?: string\n constructionInspectorDate?: Date\n supervisorInspectorDate?: Date\n overallConstructorSignature?: string\n taskConstructorSignature?: string\n overallSupervisorySignature?: string\n taskSupervisorySignature?: string\n inspectionParts?: string[]\n // checklistItems?: ChecklistItem[]\n}\n\n@customElement('sv-project-list')\nexport class SvProjectListPage extends ScopedElementsMixin(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n\n width: 100%;\n height: 100%;\n background-color: var(--md-sys-color-background, #f6f6f6);\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n div[header] {\n display: flex;\n align-items: center;\n background-color: #2ea4df1a;\n border: 1px solid #2ea4df33;\n margin: var(--spacing-large, 12px);\n margin-bottom: var(--spacing-small, 5px);\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-radius: var(--md-sys-shape-corner-small, 5px);\n\n md-filled-text-field[type='search'] {\n --md-filled-text-field-container-shape: 0px;\n --md-sys-color-primary: #2e79be;\n --md-sys-color-surface-container-highest: transparent;\n --md-filled-text-field-label-text-color: #999999;\n }\n strong {\n flex: 1;\n padding-right: var(--spacing-medium, 8px);\n text-align: right;\n }\n\n md-elevated-button[add-project] {\n font-weight: bold;\n font-size: 16px;\n margin-left: 17px;\n padding: 13px 20px;\n\n --md-sys-color-surface-container-low: #24be7b;\n --md-sys-color-primary: #ffffff;\n --md-elevated-button-container-shape: 7px;\n }\n }\n\n div[body] {\n div[project-container] {\n height: 140px;\n margin: var(--spacing-large, 12px);\n background-color: var(--md-sys-color-on-primary);\n border: 1px solid #cccccc80;\n border-radius: var(--md-sys-shape-corner-small, 5px);\n overflow: hidden;\n\n & > a {\n display: flex;\n gap: 0 var(--spacing-large, 12px);\n width: 100%;\n height: 100%;\n text-decoration: none;\n color: #000;\n }\n\n img[project-img] {\n width: 240px;\n background-color: #cccccc80;\n }\n img[project-img][no-image] {\n object-fit: contain;\n opacity: 0.5;\n }\n\n span[project-info] {\n flex: 0.55;\n padding: var(--spacing-small, 4px);\n font-size: 14px;\n\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n\n div[name] {\n color: #2e79be;\n font-weight: bold;\n font-size: 18px;\n margin: var(--spacing-small, 4px);\n }\n }\n\n span[project-state] {\n flex: 0.45;\n padding: var(--spacing-medium, 8px);\n\n & > div {\n margin: var(--spacing-tiny, 2px);\n }\n\n div[progress] {\n position: relative;\n\n md-linear-progress {\n --md-linear-progress-track-height: 18px;\n --md-linear-progress-active-indicator-height: 18px;\n --md-linear-progress-track-shape: 5px;\n --md-sys-color-primary: #0595e526;\n --md-sys-color-surface-container-highest: #0595e52a;\n }\n\n span {\n position: absolute;\n top: 0;\n left: var(--spacing-large, 12px);\n font-size: 12px;\n font-weight: bold;\n color: #2e79be;\n\n &:last-child {\n left: unset;\n right: var(--spacing-large, 12px);\n }\n }\n }\n }\n }\n }\n `\n ]\n\n get context() {\n return {\n title: '진행중 프로젝트'\n }\n }\n\n @state() private projectName: string = ''\n @state() private projectList: Project[] = []\n @state() private projectCount: number = 0\n\n render() {\n return html`\n <div header>\n <md-filled-text-field\n name=\"projectName\"\n type=\"search\"\n label=\"프로젝트명\"\n .value=${this.projectName}\n @input=${this._onInputChange}\n @keypress=${this._onKeypress}\n >\n <md-icon slot=\"leading-icon\">search</md-icon>\n </md-filled-text-field>\n\n <strong>총 ${this.projectCount}개</strong>\n </div>\n\n <div body>\n ${this.projectList?.map((project: Project) => {\n return html`\n <div project-container>\n <a href=${`kpi-dashboard?projectId=${project.id}`}>\n <img\n ?no-image=${!project.mainPhoto?.fullpath}\n project-img\n src=${project.mainPhoto?.fullpath || '/assets/images/no-image.png'}\n />\n\n <span project-info>\n <div name>${project.name}</div>\n <div content>${project.buildingComplex.address}</div>\n <div content>면적: ${project.buildingComplex?.area?.toLocaleString() || ''}㎡</div>\n <div content>착공~준공: ${project.startDate} ~ ${project.endDate}</div>\n <div content>발주처: <strong>${project.buildingComplex.clientCompany}</strong></div>\n </span>\n\n <span project-state>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.totalProgress || 0}> </md-linear-progress>\n <span>전체</span>\n <span>${project.totalProgress || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.weeklyProgress || 0}> </md-linear-progress>\n <span>주간</span>\n <span>${project.weeklyProgress || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.kpi || 0}> </md-linear-progress>\n <span>KPI</span>\n <span>${project.kpi || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.inspPassRate || 0}> </md-linear-progress>\n <span>Inspection Passing Rate</span>\n <span>${project.inspPassRate || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.robotProgressRate || 0}> </md-linear-progress>\n <span>Robot Progress</span>\n <span>${project.robotProgressRate || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.structuralSafetyRate || 0}> </md-linear-progress>\n <span>Structural safety</span>\n <span>${project.structuralSafetyRate || 0}%</span>\n </div>\n </span>\n </a>\n </div>\n `\n })}\n </div>\n `\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n this.getProjectList()\n }\n }\n\n async getProjectList() {\n const response = await client.query({\n query: gql`\n query Projects($filters: [Filter!]) {\n projects(filters: $filters) {\n items {\n id\n name\n startDate\n endDate\n mainPhoto {\n fullpath\n }\n totalProgress\n weeklyProgress\n kpi\n inspPassRate\n robotProgressRate\n structuralSafetyRate\n buildingComplex {\n address\n area\n clientCompany\n }\n }\n total\n }\n }\n `,\n variables: {\n filters: [\n {\n name: 'name',\n operator: 'search',\n value: `%${this.projectName}%`\n },\n {\n name: 'state',\n operator: 'eq',\n value: ProjectState.ONGOING\n }\n ],\n sortings: [{ name: 'createdAt', desc: true }]\n }\n })\n\n this.projectList = response.data.projects?.items || []\n this.projectCount = response.data.projects?.total || 0\n }\n\n // Input 요소의 값이 변경될 때 호출되는 콜백 함수\n private _onInputChange(event: InputEvent) {\n const target = event.target as HTMLInputElement\n this[target.name] = target.value\n }\n\n // 검색창에서 엔터입력시 검색\n private _onKeypress(event: KeyboardEvent) {\n if (event.code === 'Enter') {\n this.getProjectList()\n }\n }\n}\n"]}
1
+ {"version":3,"file":"sv-project-list.js","sourceRoot":"","sources":["../../client/pages/sv-project-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '../components/pagenation'\n\nimport { PageView } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\nimport { Attachment } from '@things-factory/attachment-base'\nimport type { FileUpload } from 'graphql-upload/GraphQLUpload.js'\n\nexport enum ProjectState {\n 'ONGOING' = '10',\n 'COMPLETED' = '20'\n}\nexport enum BuildingInspectionStatus {\n WAIT = 'WAIT',\n OVERALL_WAIT = 'OVERALL_WAIT',\n REQUEST = 'REQUEST',\n OVERALL_REQUEST = 'OVERALL_REQUEST',\n PASS = 'PASS',\n FAIL = 'FAIL'\n}\nexport const BUILDING_INSPECTION_STATUS = {\n [BuildingInspectionStatus.WAIT]: '검측 대기',\n [BuildingInspectionStatus.OVERALL_WAIT]: '검측 대기',\n [BuildingInspectionStatus.REQUEST]: '검측 요청',\n [BuildingInspectionStatus.OVERALL_REQUEST]: '검측 요청',\n [BuildingInspectionStatus.PASS]: '합격',\n [BuildingInspectionStatus.FAIL]: '불합격'\n}\n\nexport enum ProjectType {\n DSSP = 'DSSP',\n DCSP = 'DCSP',\n DKPI = 'DKPI'\n}\n\nexport interface Project {\n id?: string\n name: string\n startDate?: string\n endDate?: string\n mainPhoto?: Attachment\n mainPhotoUpload?: FileUpload\n totalProgress?: number\n weeklyProgress?: number\n kpi?: number\n inspPassRate?: number\n robotProgressRate?: number\n structuralSafetyRate?: number\n robotCount?: number\n scheduleTable?: Attachment\n buildingComplex: BuildingComplex\n projectType?: ProjectType\n}\nexport interface BuildingComplex {\n id?: string\n address?: string\n latitude?: number\n longitude?: number\n area?: number\n constructionCompany?: string\n clientCompany?: string\n designCompany?: string\n supervisoryCompany?: string\n drawing?: Attachment\n drawingUpload?: FileUpload\n constructionType?: string\n constructionCost?: number\n etc?: string\n householdCount?: number\n buildingCount?: number\n notice?: string\n planXScale?: number\n planYScale?: number\n overallConstructorEmails?: string[]\n taskConstructorEmails?: string[]\n overallSupervisoryEmails?: string[]\n taskSupervisoryEmails?: string[]\n buildings?: Building[]\n}\nexport interface Building {\n id?: string\n name: string | undefined\n floorCount: number | undefined\n hasBasement?: boolean\n basementFloorCount?: number\n drawing?: Attachment\n drawingUpload?: FileUpload\n buildingLevels?: BuildingLevel[]\n}\n\nexport interface BuildingLevel {\n id?: string\n floor?: number\n floorDisplayName?: string\n mainDrawing?: Attachment\n mainDrawingImage?: string\n mainDrawingThumbnail?: string\n mainDrawingUpload?: FileUpload\n elevationDrawing?: Attachment\n elevationDrawingThumbnail?: string\n elevationDrawingUpload?: FileUpload\n rebarDistributionDrawing?: Attachment\n rebarDistributionDrawingThumbnail?: string\n rebarDistributionDrawingUpload?: FileUpload\n etcDrawings?: Attachment[]\n etcDrawingsUpload?: FileUpload[]\n building?: Building\n buildingInspections?: BuildingInspection[]\n}\n\nexport interface BuildingInspection {\n id?: string\n attatchments?: Attachment[]\n // buildingInspectionAttachments?: BuildingInspectionAttachment[]\n status?: BuildingInspectionStatus\n requestDate?: Date\n buildingLevel?: BuildingLevel\n checklist?: Checklist\n createdAt?: Date\n updatedAt?: Date\n deletedAt?: Date\n}\n\nexport interface Checklist {\n id: string\n name?: string\n documentNo?: string\n constructionType?: string\n constructionDetailType?: string\n location?: string\n constructionInspectorDate?: Date\n supervisorInspectorDate?: Date\n overallConstructorSignature?: string\n taskConstructorSignature?: string\n overallSupervisorySignature?: string\n taskSupervisorySignature?: string\n inspectionParts?: string[]\n // checklistItems?: ChecklistItem[]\n}\n\n@customElement('sv-project-list')\nexport class SvProjectListPage extends ScopedElementsMixin(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n\n width: 100%;\n height: 100%;\n background-color: var(--md-sys-color-background, #f6f6f6);\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n div[header] {\n display: flex;\n align-items: center;\n background-color: #2ea4df1a;\n border: 1px solid #2ea4df33;\n margin: var(--spacing-large, 12px);\n margin-bottom: var(--spacing-small, 5px);\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-radius: var(--md-sys-shape-corner-small, 5px);\n\n md-filled-text-field[type='search'] {\n --md-filled-text-field-container-shape: 0px;\n --md-sys-color-primary: #2e79be;\n --md-sys-color-surface-container-highest: transparent;\n --md-filled-text-field-label-text-color: #999999;\n }\n strong {\n flex: 1;\n padding-right: var(--spacing-medium, 8px);\n text-align: right;\n }\n\n md-elevated-button[add-project] {\n font-weight: bold;\n font-size: 16px;\n margin-left: 17px;\n padding: 13px 20px;\n\n --md-sys-color-surface-container-low: #24be7b;\n --md-sys-color-primary: #ffffff;\n --md-elevated-button-container-shape: 7px;\n }\n }\n\n div[body] {\n div[project-container] {\n height: 140px;\n margin: var(--spacing-large, 12px);\n background-color: var(--md-sys-color-on-primary);\n border: 1px solid #cccccc80;\n border-radius: var(--md-sys-shape-corner-small, 5px);\n overflow: hidden;\n\n & > a {\n display: flex;\n gap: 0 var(--spacing-large, 12px);\n width: 100%;\n height: 100%;\n text-decoration: none;\n color: #000;\n }\n\n img[project-img] {\n width: 240px;\n background-color: #cccccc80;\n }\n img[project-img][no-image] {\n object-fit: contain;\n opacity: 0.5;\n }\n\n span[project-info] {\n flex: 0.55;\n padding: var(--spacing-small, 4px);\n font-size: 14px;\n\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n\n div[name] {\n color: #2e79be;\n font-weight: bold;\n font-size: 18px;\n margin: var(--spacing-small, 4px);\n }\n }\n\n span[project-state] {\n flex: 0.45;\n padding: var(--spacing-medium, 8px);\n\n & > div {\n margin: var(--spacing-tiny, 2px);\n }\n\n div[progress] {\n position: relative;\n\n md-linear-progress {\n --md-linear-progress-track-height: 18px;\n --md-linear-progress-active-indicator-height: 18px;\n --md-linear-progress-track-shape: 5px;\n --md-sys-color-primary: #0595e526;\n --md-sys-color-surface-container-highest: #0595e52a;\n }\n\n span {\n position: absolute;\n top: 0;\n left: var(--spacing-large, 12px);\n font-size: 12px;\n font-weight: bold;\n color: #2e79be;\n\n &:last-child {\n left: unset;\n right: var(--spacing-large, 12px);\n }\n }\n }\n }\n }\n }\n `\n ]\n\n get context() {\n return {\n title: '진행중 프로젝트'\n }\n }\n\n @state() private projectName: string = ''\n @state() private projectList: Project[] = []\n @state() private projectCount: number = 0\n @state() private currentPage: number = 1\n\n private readonly pageLimit: number = 20\n\n get totalPages(): number {\n return Math.max(1, Math.ceil((this.projectCount || 0) / this.pageLimit))\n }\n\n render() {\n return html`\n <div header>\n <md-filled-text-field\n name=\"projectName\"\n type=\"search\"\n label=\"프로젝트명\"\n .value=${this.projectName}\n @input=${this._onInputChange}\n @keypress=${this._onKeypress}\n >\n <md-icon slot=\"leading-icon\">search</md-icon>\n </md-filled-text-field>\n\n <strong>총 ${this.projectCount}개</strong>\n </div>\n\n <div body>\n ${this.projectList?.map((project: Project) => {\n return html`\n <div project-container>\n <a href=${`kpi-dashboard?projectId=${project.id}`}>\n <img\n ?no-image=${!project.mainPhoto?.fullpath}\n project-img\n src=${project.mainPhoto?.fullpath || '/assets/images/no-image.png'}\n />\n\n <span project-info>\n <div name>${project.name}</div>\n <div content>${project.buildingComplex.address}</div>\n <div content>면적: ${project.buildingComplex?.area?.toLocaleString() || ''}㎡</div>\n <div content>착공~준공: ${project.startDate} ~ ${project.endDate}</div>\n <div content>발주처: <strong>${project.buildingComplex.clientCompany}</strong></div>\n </span>\n\n <span project-state>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.totalProgress || 0}> </md-linear-progress>\n <span>전체</span>\n <span>${project.totalProgress || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.weeklyProgress || 0}> </md-linear-progress>\n <span>주간</span>\n <span>${project.weeklyProgress || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.kpi || 0}> </md-linear-progress>\n <span>KPI</span>\n <span>${project.kpi || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.inspPassRate || 0}> </md-linear-progress>\n <span>Inspection Passing Rate</span>\n <span>${project.inspPassRate || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.robotProgressRate || 0}> </md-linear-progress>\n <span>Robot Progress</span>\n <span>${project.robotProgressRate || 0}%</span>\n </div>\n <div progress>\n <md-linear-progress buffer=\"100\" max=\"100\" value=${project.structuralSafetyRate || 0}> </md-linear-progress>\n <span>Structural safety</span>\n <span>${project.structuralSafetyRate || 0}%</span>\n </div>\n </span>\n </a>\n </div>\n `\n })}\n </div>\n <pagenation-control\n .currentPage=${this.currentPage}\n .totalItems=${this.projectCount}\n .pageLimit=${this.pageLimit}\n @page-change=${(e: CustomEvent) => this._changePage(e.detail.page)}\n ></pagenation-control>\n `\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n this.getProjectList()\n }\n }\n\n async getProjectList() {\n const response = await client.query({\n query: gql`\n query Projects($filters: [Filter!], $sortings: [Sorting!], $pagination: Pagination) {\n projects(filters: $filters, sortings: $sortings, pagination: $pagination) {\n items {\n id\n name\n startDate\n endDate\n mainPhoto {\n fullpath\n }\n totalProgress\n weeklyProgress\n kpi\n inspPassRate\n robotProgressRate\n structuralSafetyRate\n buildingComplex {\n address\n area\n clientCompany\n }\n }\n total\n }\n }\n `,\n variables: {\n filters: [\n {\n name: 'name',\n operator: 'search',\n value: `%${this.projectName}%`\n },\n {\n name: 'state',\n operator: 'eq',\n value: ProjectState.ONGOING\n }\n ],\n sortings: [{ name: 'createdAt', desc: true }],\n pagination: { page: this.currentPage, limit: this.pageLimit }\n }\n })\n\n this.projectList = response.data.projects?.items || []\n this.projectCount = response.data.projects?.total || 0\n }\n\n // Input 요소의 값이 변경될 때 호출되는 콜백 함수\n private _onInputChange(event: InputEvent) {\n const target = event.target as HTMLInputElement\n this[target.name] = target.value\n if (target.name === 'projectName') {\n this.currentPage = 1\n }\n }\n\n // 검색창에서 엔터입력시 검색\n private _onKeypress(event: KeyboardEvent) {\n if (event.code === 'Enter') {\n this.currentPage = 1\n this.getProjectList()\n }\n }\n\n private _changePage(page: number) {\n const nextPage = Math.min(Math.max(1, page), this.totalPages)\n if (nextPage !== this.currentPage) {\n this.currentPage = nextPage\n this.getProjectList()\n }\n }\n}\n"]}