|
1 | 1 | <template> |
2 | | - <div> |
3 | | - <BaseCarousel |
4 | | - v-if="chargePointIds.length <= cardViewBreakpoint" |
5 | | - :items="chargePointIds" |
6 | | - > |
7 | | - <template #item="{ item }"> |
8 | | - <ChargePointCard :charge-point-id="item" /> |
9 | | - </template> |
10 | | - </BaseCarousel> |
| 2 | + <BaseCarousel |
| 3 | + v-if="chargePointIds.length <= cardViewBreakpoint" |
| 4 | + :items="chargePointIds" |
| 5 | + > |
| 6 | + <template #item="{ item }"> |
| 7 | + <ChargePointCard :charge-point-id="item" /> |
| 8 | + </template> |
| 9 | + </BaseCarousel> |
11 | 10 |
|
12 | | - <BaseTable |
13 | | - v-else |
14 | | - :rows="rows" |
15 | | - :columns="mobile ? columnsMobile : columns" |
16 | | - :search-input-visible="searchInputVisible" |
17 | | - :table-height="mobile ? '35vh' : '40vh'" |
18 | | - v-model:filter="filter" |
19 | | - :columns-to-search="['vehicle', 'name']" |
20 | | - @row-click="onRowClick($event as ChargePointRow)" |
21 | | - > |
22 | | - <template v-slot:body-cell-plugged="props"> |
23 | | - <q-td :props="props"> |
24 | | - <ChargePointStateIcon :charge-point-id="props.row.id" /> |
25 | | - </q-td> |
26 | | - </template> |
27 | | - </BaseTable> |
| 11 | + <BaseTable |
| 12 | + v-else |
| 13 | + :items="chargePointIds" |
| 14 | + :row-data="tableRowData" |
| 15 | + :column-config="mobile ? columnConfigMobile : columnConfig" |
| 16 | + :search-input-visible="searchInputVisible" |
| 17 | + :table-height="mobile ? '35vh' : '40vh'" |
| 18 | + v-model:filter="filter" |
| 19 | + :columns-to-search="['vehicle', 'name']" |
| 20 | + @row-click="onRowClick" |
| 21 | + > |
| 22 | + <template #body-cell-plugged="{ row }"> |
| 23 | + <q-td> |
| 24 | + <ChargePointStateIcon :charge-point-id="row.id" /> |
| 25 | + </q-td> |
| 26 | + </template> |
| 27 | + </BaseTable> |
28 | 28 |
|
29 | | - <!-- ChargePointCard Dialog --> |
30 | | - <q-dialog |
31 | | - v-model="modalChargePointCardVisible" |
32 | | - transition-show="fade" |
33 | | - transition-hide="fade" |
34 | | - :backdrop-filter="$q.screen.width < 385 ? '' : 'blur(4px)'" |
35 | | - > |
36 | | - <div class="dialog-content"> |
37 | | - <ChargePointCard |
38 | | - v-if="selectedChargePointId !== null" |
39 | | - :charge-point-id="selectedChargePointId" |
40 | | - > |
41 | | - <template #card-footer> |
42 | | - <div class="card-footer"> |
43 | | - <q-btn |
44 | | - color="primary" |
45 | | - flat |
46 | | - no-caps |
47 | | - v-close-popup |
48 | | - class="close-button" |
49 | | - size="md" |
50 | | - >Schließen</q-btn |
51 | | - > |
52 | | - </div> |
53 | | - </template> |
54 | | - </ChargePointCard> |
55 | | - </div> |
56 | | - </q-dialog> |
57 | | - </div> |
| 29 | + <!-- ChargePointCard Dialog --> |
| 30 | + <q-dialog |
| 31 | + v-model="modalChargePointCardVisible" |
| 32 | + transition-show="fade" |
| 33 | + transition-hide="fade" |
| 34 | + :backdrop-filter="$q.screen.width < 385 ? '' : 'blur(4px)'" |
| 35 | + > |
| 36 | + <div class="dialog-content"> |
| 37 | + <ChargePointCard |
| 38 | + v-if="selectedChargePointId !== null" |
| 39 | + :charge-point-id="selectedChargePointId" |
| 40 | + > |
| 41 | + <template #card-footer> |
| 42 | + <div class="card-footer"> |
| 43 | + <q-btn |
| 44 | + color="primary" |
| 45 | + flat |
| 46 | + no-caps |
| 47 | + v-close-popup |
| 48 | + class="close-button" |
| 49 | + size="md" |
| 50 | + >Schließen</q-btn |
| 51 | + > |
| 52 | + </div> |
| 53 | + </template> |
| 54 | + </ChargePointCard> |
| 55 | + </div> |
| 56 | + </q-dialog> |
58 | 57 | </template> |
59 | 58 |
|
60 | | -<style scoped> |
61 | | -.dialog-content { |
62 | | - width: auto; |
63 | | - max-width: 24em; |
64 | | -} |
65 | | -
|
66 | | -.close-button { |
67 | | - position: absolute; |
68 | | - bottom: 0.4em; |
69 | | - right: 0.4em; |
70 | | - z-index: 1; |
71 | | - background: transparent; |
72 | | -} |
73 | | -
|
74 | | -.card-footer { |
75 | | - height: 1.9em; |
76 | | -} |
77 | | -</style> |
78 | | - |
79 | 59 | <script setup lang="ts"> |
80 | 60 | import { computed, ref } from 'vue'; |
81 | | -import { useQuasar, Platform, QTableColumn } from 'quasar'; |
| 61 | +import { Platform } from 'quasar'; |
82 | 62 | import { useMqttStore } from 'src/stores/mqtt-store'; |
| 63 | +import { useChargeModes } from 'src/composables/useChargeModes'; |
83 | 64 | import BaseCarousel from 'src/components/BaseCarousel.vue'; |
84 | 65 | import BaseTable from 'src/components/BaseTable.vue'; |
85 | 66 | import ChargePointCard from 'src/components/ChargePointCard.vue'; |
86 | 67 | import ChargePointStateIcon from 'src/components/ChargePointStateIcon.vue'; |
87 | | -import { useChargeModes } from 'src/composables/useChargeModes'; |
88 | | -import { ChargePointRow } from 'src/components/models/charge-point-information-models'; |
89 | 68 |
|
90 | | -const $q = useQuasar(); |
91 | | -const mobile = computed(() => Platform.is.mobile); |
92 | 69 | const mqttStore = useMqttStore(); |
93 | | -const selectedChargePointId = ref<number | null>(null); |
94 | | -const modalChargePointCardVisible = ref(false); |
95 | | -const filter = ref(''); |
| 70 | +const { chargeModes } = useChargeModes(); |
96 | 71 | const chargePointIds = computed(() => mqttStore.chargePointIds); |
97 | 72 | const cardViewBreakpoint = computed( |
98 | | - () => mqttStore.themeConfiguration?.card_view_breakpoint || 4, |
| 73 | + () => mqttStore.themeConfiguration?.chargePoint_card_view_breakpoint || 4, |
99 | 74 | ); |
100 | 75 | const searchInputVisible = computed( |
101 | | - () => mqttStore.themeConfiguration?.table_search_input_field, |
| 76 | + () => mqttStore.themeConfiguration?.chargePoint_table_search_input_field, |
102 | 77 | ); |
103 | | -const { chargeModes } = useChargeModes(); |
104 | | -
|
105 | | -const rows = computed<ChargePointRow[]>(() => { |
106 | | - return chargePointIds.value.map((id) => { |
107 | | - const chargePointName = mqttStore.chargePointName(id); |
108 | | - const vehicleName = |
| 78 | +const mobile = computed(() => Platform.is.mobile); |
| 79 | +const selectedChargePointId = ref<number | null>(null); |
| 80 | +const modalChargePointCardVisible = ref(false); |
| 81 | +const filter = ref(''); |
| 82 | +const tableRowData = computed(() => { |
| 83 | + return (id: number) => { |
| 84 | + const name = mqttStore.chargePointName(id); |
| 85 | + const vehicle = |
109 | 86 | mqttStore.chargePointConnectedVehicleInfo(id).value?.name || |
110 | 87 | 'Kein Fahrzeug'; |
111 | | - const plugState = mqttStore.chargePointPlugState(id) ? 'Ja' : 'Nein'; |
| 88 | + const plugged = mqttStore.chargePointPlugState(id) ? 'Ja' : 'Nein'; |
112 | 89 | const chargeModeValue = |
113 | 90 | mqttStore.chargePointConnectedVehicleChargeMode(id).value; |
114 | 91 | const chargeModeObj = chargeModes.find( |
115 | 92 | (mode) => mode.value === chargeModeValue, |
116 | 93 | ); |
117 | 94 | const chargeMode = chargeModeObj ? chargeModeObj.label : chargeModeValue; |
118 | | - const soc = Math.round( |
119 | | - mqttStore.chargePointConnectedVehicleSoc(id).value?.soc || 0, |
120 | | - ); |
121 | | - const socDisplay = `${soc}%`; |
| 95 | + const chargePointSoc = |
| 96 | + mqttStore.chargePointConnectedVehicleSoc(id).value?.soc; |
| 97 | + const soc = |
| 98 | + chargePointSoc !== undefined ? `${Math.round(chargePointSoc)}%` : '0%'; |
122 | 99 | const power = mqttStore.chargePointPower(id, 'textValue'); |
123 | | - const energyCharged = mqttStore.chargePointEnergyChargedPlugged( |
124 | | - id, |
125 | | - 'textValue', |
126 | | - ); |
| 100 | + const charged = mqttStore.chargePointEnergyChargedPlugged(id, 'textValue'); |
127 | 101 | return { |
128 | | - id: id, |
129 | | - name: chargePointName, |
130 | | - vehicle: vehicleName, |
131 | | - plugged: plugState, |
132 | | - mode: chargeMode, |
133 | | - soc: socDisplay, |
134 | | - power: power, |
135 | | - charged: energyCharged, |
| 102 | + id, |
| 103 | + name, |
| 104 | + vehicle, |
| 105 | + plugged, |
| 106 | + chargeMode, |
| 107 | + soc, |
| 108 | + power, |
| 109 | + charged, |
136 | 110 | }; |
137 | | - }); |
| 111 | + }; |
138 | 112 | }); |
139 | 113 |
|
140 | | -const columns: QTableColumn[] = [ |
141 | | - { |
142 | | - name: 'name', |
143 | | - label: 'Ladepunkt', |
144 | | - field: 'name', |
145 | | - sortable: true, |
146 | | - align: 'left', |
147 | | - headerStyle: 'font-weight: bold', |
148 | | - }, |
149 | | - { |
150 | | - name: 'vehicle', |
151 | | - label: 'Fahrzeug', |
152 | | - field: 'vehicle', |
153 | | - sortable: true, |
154 | | - align: 'left', |
155 | | - headerStyle: 'font-weight: bold', |
156 | | - }, |
157 | | - { |
158 | | - name: 'plugged', |
159 | | - label: 'Status', |
160 | | - field: 'plugged', |
161 | | - sortable: true, |
162 | | - align: 'center', |
163 | | - headerStyle: 'font-weight: bold', |
164 | | - }, |
165 | | - { |
166 | | - name: 'mode', |
167 | | - label: 'Lademodus', |
168 | | - field: 'mode', |
169 | | - sortable: true, |
170 | | - align: 'left', |
171 | | - headerStyle: 'font-weight: bold', |
172 | | - }, |
173 | | - { |
174 | | - name: 'soc', |
175 | | - label: 'Ladestand', |
176 | | - field: 'soc', |
177 | | - sortable: true, |
178 | | - align: 'right', |
179 | | - headerStyle: 'font-weight: bold', |
180 | | - }, |
181 | | - { |
182 | | - name: 'power', |
183 | | - label: 'Leistung', |
184 | | - field: 'power', |
185 | | - sortable: true, |
186 | | - align: 'right', |
187 | | - headerStyle: 'font-weight: bold', |
| 114 | +const columnConfig = { |
| 115 | + fields: [ |
| 116 | + 'name', |
| 117 | + 'vehicle', |
| 118 | + 'plugged', |
| 119 | + 'chargeMode', |
| 120 | + 'soc', |
| 121 | + 'power', |
| 122 | + 'charged', |
| 123 | + ], |
| 124 | + labels: { |
| 125 | + name: 'Ladepunkt', |
| 126 | + vehicle: 'Fahrzeug', |
| 127 | + plugged: 'Status', |
| 128 | + chargeMode: 'Lademodus', |
| 129 | + soc: 'Ladestand', |
| 130 | + power: 'Leistung', |
| 131 | + charged: 'Geladen', |
188 | 132 | }, |
189 | | - { |
190 | | - name: 'charged', |
191 | | - label: 'Geladen', |
192 | | - field: 'charged', |
193 | | - sortable: true, |
194 | | - align: 'right', |
195 | | - headerStyle: 'font-weight: bold', |
196 | | - }, |
197 | | -]; |
| 133 | +}; |
198 | 134 |
|
199 | | -const columnsMobile = computed((): QTableColumn[] => { |
200 | | - return [ |
201 | | - { |
202 | | - name: 'name', |
203 | | - label: 'Ladepunkt', |
204 | | - field: 'name', |
205 | | - sortable: true, |
206 | | - align: 'left', |
207 | | - headerStyle: 'font-weight: bold', |
208 | | - }, |
209 | | - { |
210 | | - name: 'vehicle', |
211 | | - label: 'Fahrzeug', |
212 | | - field: 'vehicle', |
213 | | - sortable: true, |
214 | | - align: 'left', |
215 | | - headerStyle: 'font-weight: bold', |
216 | | - }, |
217 | | - { |
218 | | - name: 'plugged', |
219 | | - label: 'Status', |
220 | | - field: 'plugged', |
221 | | - sortable: true, |
222 | | - align: 'center', |
223 | | - headerStyle: 'font-weight: bold', |
224 | | - }, |
225 | | - ]; |
226 | | -}); |
| 135 | +const columnConfigMobile = { |
| 136 | + fields: ['name', 'vehicle', 'plugged'], |
| 137 | + labels: { |
| 138 | + name: 'Ladepunkt', |
| 139 | + vehicle: 'Fahrzeug', |
| 140 | + plugged: 'Status', |
| 141 | + }, |
| 142 | +}; |
227 | 143 |
|
228 | | -const onRowClick = (row: ChargePointRow) => { |
229 | | - selectedChargePointId.value = row.id; |
| 144 | +const onRowClick = (row: Record<string, unknown>) => { |
| 145 | + selectedChargePointId.value = row.id as number; |
230 | 146 | modalChargePointCardVisible.value = true; |
231 | 147 | }; |
232 | 148 | </script> |
| 149 | + |
| 150 | +<style scoped> |
| 151 | +.dialog-content { |
| 152 | + width: auto; |
| 153 | + max-width: 24em; |
| 154 | +} |
| 155 | +
|
| 156 | +.close-button { |
| 157 | + position: absolute; |
| 158 | + bottom: 0.4em; |
| 159 | + right: 0.4em; |
| 160 | + z-index: 1; |
| 161 | + background: transparent; |
| 162 | +} |
| 163 | +
|
| 164 | +.card-footer { |
| 165 | + height: 1.9em; |
| 166 | +} |
| 167 | +</style> |
0 commit comments