2323 :disabled =" loading || props.rating.rating_user === 0"
2424 :class =" {
2525 'px-2 py-1 text-sm rounded transition-colors': true,
26- 'bg-red-600 hover:bg-red-700 text-white': props.rating.rating_user > 0 && !loading,
26+ 'bg-red-600 hover:bg-red-700 text-white hover:cursor-pointer ': props.rating.rating_user > 0 && !loading,
2727 'bg-gray-500 text-gray-300 cursor-not-allowed': loading || props.rating.rating_user === 0,
2828 }"
29- @click =" handleRatingClick(0)"
29+ @click =" handleRatingClick(props.photoId, 0)"
3030 >
3131 ×
3232 </button >
4343 }"
4444 @mouseenter =" handleMouseEnter(rating)"
4545 @mouseleave =" handleMouseLeave()"
46- @click =" handleRatingClick(rating as 1 | 2 | 3 | 4 | 5)"
46+ @click =" handleRatingClick(props.photoId, rating as 1 | 2 | 3 | 4 | 5)"
4747 >
4848 <i
4949 :class =" {
6363</template >
6464
6565<script setup lang="ts">
66- import { ref } from " vue" ;
6766import { useLycheeStateStore } from " @/stores/LycheeState" ;
6867import { usePhotoStore } from " @/stores/PhotoState" ;
6968import { useToast } from " primevue/usetoast" ;
70- import PhotoService from " @/services/photo-service" ;
7169import { useUserStore } from " @/stores/UserState" ;
7270import StarRow from " @/components/icons/StarRow.vue" ;
71+ import { useRating } from " @/composables/photo/useRating" ;
7372
7473const lycheeStore = useLycheeStateStore ();
7574const photoStore = usePhotoStore ();
7675const userStore = useUserStore ();
7776const toast = useToast ();
7877
79- const loading = ref (false );
80- const hoverRating = ref <number | null >(null );
78+ const { hoverRating, loading, handleRatingClick } = useRating (photoStore , toast , userStore );
8179
8280const props = defineProps <{
8381 photoId: string ;
@@ -93,52 +91,4 @@ function handleMouseEnter(rating: number) {
9391function handleMouseLeave() {
9492 hoverRating .value = null ;
9593}
96-
97- function handleRatingClick(rating : 0 | 1 | 2 | 3 | 4 | 5 ) {
98- if (loading .value ) {
99- return ;
100- }
101-
102- loading .value = true ;
103-
104- PhotoService .setRating (props .photoId , rating )
105- .then ((response ) => {
106- // Update photo store with new photo data (includes updated rating)
107- photoStore .photo = response .data ;
108-
109- // Show success message
110- const message = rating === 0 ? " gallery.photo.rating.removed" : " gallery.photo.rating.saved" ;
111- toast .add ({
112- severity: " success" ,
113- summary: " Success" ,
114- detail: message ,
115- life: 3000 ,
116- });
117- })
118- .catch ((error ) => {
119- console .error (" Failed to save rating:" , error );
120-
121- // Show error toast
122- let errorMessage = " gallery.photo.rating.error" ;
123-
124- if (error .response ?.status === 401 ) {
125- errorMessage = " gallery.photo.rating.error_unauthorized" ;
126- } else if (error .response ?.status === 403 ) {
127- errorMessage = " gallery.photo.rating.error_forbidden" ;
128- } else if (error .response ?.status === 404 ) {
129- errorMessage = " gallery.photo.rating.error_not_found" ;
130- }
131-
132- toast .add ({
133- severity: " error" ,
134- summary: " Error" ,
135- detail: errorMessage ,
136- life: 5000 ,
137- });
138- })
139- .finally (() => {
140- loading .value = false ;
141- hoverRating .value = null ;
142- });
143- }
14494 </script >
0 commit comments