--- client/views/pages/main/Dashboard.vue
+++ client/views/pages/main/Dashboard.vue
... | ... | @@ -232,8 +232,13 @@ |
232 | 232 |
<span class=" title1 ml30">{{ selectedImage.unit }}을 마친 <em class="yellow">{{ |
233 | 233 |
selectedImage.name }}</em>친구</span> |
234 | 234 |
</div> |
235 |
- <div class="title2 flex align-center" style="gap: 10px;"><svg-icon type="mdi" :path="mdiHeart" |
|
236 |
- style="color: #FFBA08;"></svg-icon> |
|
235 |
+ <div class="title2 flex align-center" style="gap: 10px;"> |
|
236 |
+ <svg-icon v-if="!isHeartFilled" type="mdi" :path="mdiHeartOutline" |
|
237 |
+ @click="toggleHeart(selectedImage.heart, selectedImage.fileMngId)" |
|
238 |
+ style="color: #FFBA08; cursor: pointer;"></svg-icon> |
|
239 |
+ <svg-icon v-if="isHeartFilled" type="mdi" :path="mdiHeart" |
|
240 |
+ @click="toggleHeart(selectedImage.heart, selectedImage.fileMngId)" |
|
241 |
+ style="color: #FFBA08; cursor: pointer;"></svg-icon> |
|
237 | 242 |
<p><em class="yellow">{{ selectedImage.heart }}</em></p> |
238 | 243 |
</div> |
239 | 244 |
</div> |
... | ... | @@ -246,7 +251,9 @@ |
246 | 251 |
<script> |
247 | 252 |
import SvgIcon from '@jamescoyle/vue-icon'; |
248 | 253 |
import { mdiMagnify, mdiHeart, mdiWindowClose } from '@mdi/js'; |
254 |
+import { mdiHeartOutline } from '@mdi/js'; |
|
249 | 255 |
import axios from 'axios'; |
256 |
+import { call } from 'file-loader'; |
|
250 | 257 |
import { name } from 'file-loader'; |
251 | 258 |
import { mapGetters } from 'vuex'; |
252 | 259 |
import { mapActions } from "vuex"; |
... | ... | @@ -266,6 +273,7 @@ |
266 | 273 |
mdiMagnify: mdiMagnify, |
267 | 274 |
mdiWindowClose: mdiWindowClose, |
268 | 275 |
mdiHeart: mdiHeart, |
276 |
+ mdiHeartOutline: mdiHeartOutline, |
|
269 | 277 |
showModal: false, |
270 | 278 |
searchOpen: false, // 사진 상세보기 모달창 |
271 | 279 |
searchOpen2: false, // 단원 마친 후, 사진 촬영 여부 선택 모달창 |
... | ... | @@ -305,12 +313,33 @@ |
305 | 313 |
unit: '', |
306 | 314 |
date: '', |
307 | 315 |
name: '', |
308 |
- heart: '' |
|
316 |
+ heart: '', |
|
317 |
+ fileMngId: '', |
|
309 | 318 |
}, |
310 | 319 |
], |
320 |
+ |
|
321 |
+ isHeartFilled: false, // 하트가 채워졌는지 여부 |
|
311 | 322 |
} |
312 | 323 |
}, |
313 | 324 |
methods: { |
325 |
+ toggleHeart(heart, fileMngId) { |
|
326 |
+ this.isHeartFilled = !this.isHeartFilled; // 하트 상태 토글 |
|
327 |
+ |
|
328 |
+ if (this.isHeartFilled) var calHeart = heart + 1; |
|
329 |
+ else var calHeart = heart - 1 |
|
330 |
+ |
|
331 |
+ // 하트 수를 증가시키기 위한 API 요청 |
|
332 |
+ axios.post('/photo/likeUpdate.json', { |
|
333 |
+ "likeData": calHeart, |
|
334 |
+ "fileMngId": fileMngId |
|
335 |
+ }) |
|
336 |
+ .then(response => { |
|
337 |
+ this.selectedImage.heart = calHeart; |
|
338 |
+ }) |
|
339 |
+ .catch(error => { |
|
340 |
+ console.error("Error updating heart:", error); |
|
341 |
+ }); |
|
342 |
+ }, |
|
314 | 343 |
checkAndFetchData() { |
315 | 344 |
console.log("받은 Book ID:", this.getBookId); |
316 | 345 |
console.log("받은 Unit ID:", this.getUnitId); |
... | ... | @@ -336,11 +365,13 @@ |
336 | 365 |
|
337 | 366 |
//은진 |
338 | 367 |
buttonSearch(image) { |
368 |
+ this.isHeartFilled = false; |
|
339 | 369 |
this.selectedImage.name = image.stdId; |
340 | 370 |
this.selectedImage.image = image.url; |
341 | 371 |
this.selectedImage.unit = this.titleUnitName; |
342 | 372 |
this.selectedImage.date = image.fileRegDate.split(" ")[0]; |
343 | 373 |
this.selectedImage.heart = image.likeData; |
374 |
+ this.selectedImage.fileMngId = image.fileMngId; |
|
344 | 375 |
this.searchOpen = true; |
345 | 376 |
}, |
346 | 377 |
fetchImage(unit_id) { |
... | ... | @@ -365,7 +396,6 @@ |
365 | 396 |
return Promise.all(findFilePromises); |
366 | 397 |
}) |
367 | 398 |
.then(fileResults => { |
368 |
- // Assuming this.file and fileResults are of the same length |
|
369 | 399 |
this.images = this.file.map((file, index) => { |
370 | 400 |
const result = fileResults[index]; |
371 | 401 |
if (result) { |
... | ... | @@ -374,8 +404,9 @@ |
374 | 404 |
fileId: result.fileId, |
375 | 405 |
fileNm: result.fileNm, |
376 | 406 |
fileRegDate: result.regDt, |
377 |
- likeData: file.like_data, // Add like_data from this.file |
|
378 |
- stdId: file.user_nm // Add std_id from this.file |
|
407 |
+ likeData: file.like_data, |
|
408 |
+ stdId: file.user_nm, |
|
409 |
+ fileMngId: result.fileMngId, |
|
379 | 410 |
}; |
380 | 411 |
} |
381 | 412 |
return null; |
... | ... | @@ -555,8 +586,9 @@ |
555 | 586 |
this.closeModal(); // 모달창을 닫음 |
556 | 587 |
}); |
557 | 588 |
}, |
558 |
- closeModal() { //웹캠 및 모든 팝업 닫기 |
|
559 |
- // this.showModal = false; |
|
589 |
+ closeModal() { |
|
590 |
+ |
|
591 |
+ |
|
560 | 592 |
this.searchOpen = false; |
561 | 593 |
this.searchOpen2 = false; |
562 | 594 |
this.showCameraModal = false; |
--- client/views/pages/main/PhotoBook.vue
+++ client/views/pages/main/PhotoBook.vue
... | ... | @@ -6,46 +6,25 @@ |
6 | 6 |
<div> |
7 | 7 |
<div class="title-box flex justify-end mb40"> |
8 | 8 |
<select name="" id=""> |
9 |
- <option |
|
10 |
- v-for="classItem in classList" |
|
11 |
- :key="classItem.sclsId" |
|
12 |
- :value="classItem.sclsId" |
|
13 |
- @click=" |
|
14 |
- currentPage = 1; |
|
15 |
- stdPhotoSelectList(classItem.sclsId); |
|
16 |
- " |
|
17 |
- > |
|
9 |
+ <option v-for="classItem in classList" :key="classItem.sclsId" :value="classItem.sclsId" @click=" |
|
10 |
+ currentPage = 1; |
|
11 |
+ stdPhotoSelectList(classItem.sclsId); |
|
12 |
+ "> |
|
18 | 13 |
{{ classItem.sclsNm }} |
19 | 14 |
</option> |
20 | 15 |
</select> |
21 | 16 |
</div> |
22 | 17 |
<div class="btnGroup" style="display: flex; flex-direction: column"> |
23 |
- <button |
|
24 |
- v-for="n in totalPages" |
|
25 |
- :key="n" |
|
26 |
- @click="changePage(n)" |
|
27 |
- type="button" |
|
28 |
- title="페이지 버튼" |
|
29 |
- class="tab-btn" |
|
30 |
- > |
|
31 |
- <img |
|
32 |
- v-if="currentPage !== n" |
|
33 |
- src="../../../resources/img/btn49_15s_normal.png" |
|
34 |
- alt="" |
|
35 |
- /> |
|
18 |
+ <button v-for="n in totalPages" :key="n" @click="changePage(n)" type="button" title="페이지 버튼" class="tab-btn"> |
|
19 |
+ <img v-if="currentPage !== n" src="../../../resources/img/btn49_15s_normal.png" alt="" /> |
|
36 | 20 |
<img v-else src="../../../resources/img/btn49_15s_click.png" alt="" /> |
37 | 21 |
<p :class="{ 'custom-style': currentPage === n }">{{ n }}</p> |
38 | 22 |
</button> |
39 | 23 |
</div> |
40 | 24 |
<div v-if="selectedTab === 'tab1'" class="tab-box"> |
41 | 25 |
<div class="flex justify-between"> |
42 |
- <div |
|
43 |
- v-for="(photo, index) in (photoList?.result || []).slice(0, 3)" |
|
44 |
- :key="index" |
|
45 |
- class="photo" |
|
46 |
- :style="{ transform: getRotation(index) }" |
|
47 |
- @click="buttonSearch(photo)" |
|
48 |
- > |
|
26 |
+ <div v-for="(photo, index) in (photoList?.result || []).slice(0, 3)" :key="index" class="photo" |
|
27 |
+ :style="{ transform: getRotation(index) }" @click="buttonSearch(photo)"> |
|
49 | 28 |
<div class="class"> |
50 | 29 |
<div class="box"> |
51 | 30 |
<div class="photo-container"> |
... | ... | @@ -60,21 +39,12 @@ |
60 | 39 |
</div> |
61 | 40 |
</div> |
62 | 41 |
<div class="flex justify-between mt20"> |
63 |
- <div |
|
64 |
- v-for="(photo, index) in (photoList?.result || []).slice(3, 6)" |
|
65 |
- :key="index + 3" |
|
66 |
- class="photo" |
|
67 |
- :style="{ transform: getRotation(index + 3) }" |
|
68 |
- @click="buttonSearch(photo)" |
|
69 |
- > |
|
42 |
+ <div v-for="(photo, index) in (photoList?.result || []).slice(3, 6)" :key="index + 3" class="photo" |
|
43 |
+ :style="{ transform: getRotation(index + 3) }" @click="buttonSearch(photo)"> |
|
70 | 44 |
<div class="class"> |
71 | 45 |
<div class="box"> |
72 | 46 |
<div class="photo-container"> |
73 |
- <img |
|
74 |
- :src="fetchImage(photo.fileRpath)" |
|
75 |
- alt="" |
|
76 |
- style="width: 150px" |
|
77 |
- /> |
|
47 |
+ <img :src="fetchImage(photo.fileRpath)" alt="" style="width: 150px" /> |
|
78 | 48 |
</div> |
79 | 49 |
</div> |
80 | 50 |
<div class="photo-text mt10 ml10"> |
... | ... | @@ -90,32 +60,20 @@ |
90 | 60 |
<div class="flex mb10 justify-between"> |
91 | 61 |
<p class="popup-title">알림</p> |
92 | 62 |
<button type="button" class="popup-close-btn" @click="closeBtn"> |
93 |
- <svg-icon |
|
94 |
- type="mdi" |
|
95 |
- :path="mdiWindowClose" |
|
96 |
- class="close-btn" |
|
97 |
- ></svg-icon> |
|
63 |
+ <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> |
|
98 | 64 |
</button> |
99 | 65 |
</div> |
100 | 66 |
|
101 |
- <div |
|
102 |
- class="photo-modal flex justify-between mt20" |
|
103 |
- v-if="photoData.length > 0" |
|
104 |
- > |
|
67 |
+ <div class="photo-modal flex justify-between mt20" v-if="photoData.length > 0"> |
|
105 | 68 |
<div class="box"> |
106 | 69 |
<div> |
107 |
- <img |
|
108 |
- :src="fetchImage(photoData[0].fileRpath)" |
|
109 |
- alt="" |
|
110 |
- style="width: 640px; height: 480px" |
|
111 |
- /> |
|
70 |
+ <img :src="fetchImage(photoData[0].fileRpath)" alt="" style="width: 640px; height: 480px" /> |
|
112 | 71 |
</div> |
113 | 72 |
</div> |
114 | 73 |
<div class="photo-title-container"> |
115 | 74 |
<div class="title1"> |
116 | 75 |
{{ photoData[0].unitName }}을 마친 |
117 |
- <em class="yellow">{{ photoData[0].stdName }}</em |
|
118 |
- >친구 |
|
76 |
+ <em class="yellow">{{ photoData[0].stdName }}</em>친구 |
|
119 | 77 |
</div> |
120 | 78 |
<p class="title2 date">{{ photoData[0].photoDate }}</p> |
121 | 79 |
</div> |
... | ... | @@ -324,14 +282,16 @@ |
324 | 282 |
}; |
325 | 283 |
</script> |
326 | 284 |
|
327 |
-<style> |
|
285 |
+<style scoped> |
|
328 | 286 |
.btnGroup button { |
329 | 287 |
cursor: pointer; |
330 | 288 |
z-index: 100000; |
331 | 289 |
} |
290 |
+ |
|
332 | 291 |
.popup-wrap { |
333 | 292 |
z-index: 10000000; |
334 | 293 |
} |
294 |
+ |
|
335 | 295 |
.popup-box { |
336 | 296 |
top: 500px; |
337 | 297 |
width: 950px; |
... | ... | @@ -357,6 +317,7 @@ |
357 | 317 |
flex-direction: column; |
358 | 318 |
gap: 5px; |
359 | 319 |
} |
320 |
+ |
|
360 | 321 |
.photo-modal { |
361 | 322 |
flex-direction: column; |
362 | 323 |
} |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?