Quellcode durchsuchen

refactor: Converted SongItem to Vue composition API

Kristian Vos vor 2 Jahren
Ursprung
Commit
d4ade17b7f
1 geänderte Dateien mit 108 neuen und 114 gelöschten Zeilen
  1. 108 114
      frontend/src/components/SongItem.vue

+ 108 - 114
frontend/src/components/SongItem.vue

@@ -1,3 +1,111 @@
+<script setup lang="ts">
+import { useStore } from "vuex";
+import { ref, computed, onMounted, onUnmounted } from "vue";
+import { formatDistance, parseISO } from "date-fns";
+import AddToPlaylistDropdown from "./AddToPlaylistDropdown.vue";
+import utils from "@/utils";
+
+const store = useStore();
+
+const props = defineProps({
+	song: {
+		type: Object,
+		default: () => {}
+	},
+	requestedBy: {
+		type: Boolean,
+		default: false
+	},
+	duration: {
+		type: Boolean,
+		default: true
+	},
+	thumbnail: {
+		type: Boolean,
+		default: true
+	},
+	disabledActions: {
+		type: Array,
+		default: () => []
+	},
+	header: {
+		type: String,
+		default: null
+	}
+});
+
+const formatedRequestedAt = ref(null);
+const formatRequestedAtInterval = ref();
+const hoveredTippy = ref(false);
+const songActions = ref(null);
+
+const loggedIn = computed(() => store.state.user.auth.loggedIn);
+const userRole = computed(() => store.state.user.auth.userRole);
+
+function formatRequestedAt() {
+	if (props.requestedBy && props.song.requestedAt)
+		formatedRequestedAt.value = formatDistance(
+			parseISO(props.song.requestedAt),
+			new Date()
+		);
+}
+function formatArtists() {
+	if (props.song.artists.length === 1) {
+		return props.song.artists[0];
+	}
+	if (props.song.artists.length === 2) {
+		return props.song.artists.join(" & ");
+	}
+	if (props.song.artists.length > 2) {
+		return `${props.song.artists
+			.slice(0, -1)
+			.join(", ")} & ${props.song.artists.slice(-1)}`;
+	}
+	return null;
+}
+function hideTippyElements() {
+	songActions.value.tippy.hide();
+
+	setTimeout(
+		() =>
+			Array.from(document.querySelectorAll(".tippy-popper")).forEach(
+				popper => popper._tippy.hide()
+			),
+		500
+	);
+}
+function hoverTippy() {
+	hoveredTippy.value = true;
+}
+function openModal(payload) {
+	store.dispatch("modalVisibility/openModal", payload);
+}
+function report(song) {
+	hideTippyElements();
+	openModal({ modal: "report", data: { song } });
+}
+function edit(song) {
+	hideTippyElements();
+	openModal({
+		modal: "editSong",
+		data: { song }
+	});
+}
+
+onMounted(() => {
+	if (props.requestedBy) {
+		formatRequestedAt();
+		formatRequestedAtInterval.value = setInterval(() => {
+			formatRequestedAt();
+		}, 30000);
+	}
+});
+
+onUnmounted(() => {
+	clearInterval(formatRequestedAtInterval.value);
+});
+</script>
+
 <template>
 	<div
 		class="universal-item song-item"
@@ -166,120 +274,6 @@
 	</div>
 </template>
 
-<script>
-import { mapActions, mapState } from "vuex";
-import { formatDistance, parseISO } from "date-fns";
-
-import AddToPlaylistDropdown from "./AddToPlaylistDropdown.vue";
-import utils from "@/utils";
-
-export default {
-	components: { AddToPlaylistDropdown },
-	props: {
-		song: {
-			type: Object,
-			default: () => {}
-		},
-		requestedBy: {
-			type: Boolean,
-			default: false
-		},
-		duration: {
-			type: Boolean,
-			default: true
-		},
-		thumbnail: {
-			type: Boolean,
-			default: true
-		},
-		disabledActions: {
-			type: Array,
-			default: () => []
-		},
-		header: {
-			type: String,
-			default: null
-		}
-	},
-	data() {
-		return {
-			utils,
-			formatedRequestedAt: null,
-			formatRequestedAtInterval: null,
-			hoveredTippy: false
-		};
-	},
-	computed: {
-		...mapState({
-			loggedIn: state => state.user.auth.loggedIn,
-			userRole: state => state.user.auth.role
-		})
-	},
-	mounted() {
-		if (this.requestedBy) {
-			this.formatRequestedAt();
-			this.formatRequestedAtInterval = setInterval(() => {
-				this.formatRequestedAt();
-			}, 30000);
-		}
-	},
-	unmounted() {
-		clearInterval(this.formatRequestedAtInterval);
-	},
-	methods: {
-		formatRequestedAt() {
-			if (this.requestedBy && this.song.requestedAt)
-				this.formatedRequestedAt = this.formatDistance(
-					parseISO(this.song.requestedAt),
-					new Date()
-				);
-		},
-		formatArtists() {
-			if (this.song.artists.length === 1) {
-				return this.song.artists[0];
-			}
-			if (this.song.artists.length === 2) {
-				return this.song.artists.join(" & ");
-			}
-			if (this.song.artists.length > 2) {
-				return `${this.song.artists
-					.slice(0, -1)
-					.join(", ")} & ${this.song.artists.slice(-1)}`;
-			}
-			return null;
-		},
-		hideTippyElements() {
-			this.$refs.songActions.tippy.hide();
-
-			setTimeout(
-				() =>
-					Array.from(
-						document.querySelectorAll(".tippy-popper")
-					).forEach(popper => popper._tippy.hide()),
-				500
-			);
-		},
-		hoverTippy() {
-			this.hoveredTippy = true;
-		},
-		report(song) {
-			this.hideTippyElements();
-			this.openModal({ modal: "report", data: { song } });
-		},
-		edit(song) {
-			this.hideTippyElements();
-			this.openModal({
-				modal: "editSong",
-				data: { song }
-			});
-		},
-		...mapActions("modalVisibility", ["openModal"]),
-		formatDistance,
-		parseISO
-	}
-};
-</script>
-
 <style lang="less" scoped>
 .night-mode {
 	.song-item {