🔷 add Update playlist modal

This commit is contained in:
geoffrey45 2022-04-08 06:46:45 +03:00
parent 0e946974a3
commit 657daa389f
5 changed files with 312 additions and 18 deletions

View File

@ -1,12 +1,25 @@
<template>
<div class="p-header">
<div
class="p-header image"
:style="[
{
backgroundImage: `url(${props.info.image})`,
},
]"
>
<div class="gradient"></div>
<div class="carddd">
<div class="art image shadow-sm"></div>
<div class="info">
<div class="btns">
<PlayBtnRect :source="playSources.playlist" />
</div>
<div class="duration">{{props.info.count}} Tracks 3 Hours</div>
<div class="duration">
<span v-if="props.info.count == 0">No Tracks</span>
<span v-else-if="props.info.count == 1"
>{{ props.info.count }} Track</span
>
<span v-else>{{ props.info.count }} Tracks</span> 3 Hours
</div>
<div class="desc">
{{ props.info.description }}
</div>
@ -18,7 +31,7 @@
<span class="status"
>Last updated {{ props.info.lastUpdated }} |&#160;</span
>
<span class="edit">Edit</span>
<span class="edit" @click="editPlaylist">Edit</span>
</div>
</div>
</template>
@ -26,23 +39,45 @@
<script setup lang="ts">
import { playSources } from "../../composables/enums";
import { Playlist } from "../../interfaces";
import PlayBtnRect from "../shared/PlayBtnRect.vue";
import useModalStore from "../../stores/modal";
const modal = useModalStore();
const props = defineProps<{
info: Playlist;
}>();
function editPlaylist() {
modal.showEditPlaylistModal(props.info);
}
</script>
<style lang="scss">
.p-header {
display: grid;
grid-template-columns: 1fr;
height: 14rem;
background-image: linear-gradient(37deg, $black 4%, $accent, $black);
height: 16rem;
position: relative;
margin-top: $small;
border-radius: 0.75rem;
color: $white;
background-color: transparent;
.gradient {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: linear-gradient(
37deg,
$black 20%,
transparent,
$black 90%
);
border-radius: 0.5rem;
}
.last-updated {
position: absolute;
@ -54,6 +89,7 @@ const props = defineProps<{
font-size: 0.9rem;
border-radius: $smaller;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.479);
z-index: 12;
@include phone-only {
bottom: 1rem;
@ -74,13 +110,19 @@ const props = defineProps<{
width: 100%;
padding: 1rem;
display: grid;
grid-template-columns: 13rem 1fr;
z-index: 10;
.art {
width: 12rem;
height: 12rem;
background-color: red;
background-image: url("../../assets/images/eggs.jpg");
width: 100%;
height: 100%;
display: flex;
align-items: flex-end;
.image {
width: 12rem;
height: 12rem;
background-image: url("../../assets/images/eggs.jpg");
}
}
.info {
@ -105,6 +147,7 @@ const props = defineProps<{
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
max-width: 50%;
}
.duration {

View File

@ -10,6 +10,12 @@
@hideModal="hideModal"
@title="title"
/>
<UpdatePlaylist
:playlist="modal.props"
v-if="modal.component == modal.options.updatePlaylist"
@hideModal="hideModal"
@title="title"
/>
</div>
</div>
</template>
@ -17,6 +23,7 @@
<script setup lang="ts">
import useModalStore from "../stores/modal";
import NewPlaylist from "./modals/NewPlaylist.vue";
import UpdatePlaylist from "./modals/updatePlaylist.vue";
const modal = useModalStore();
@ -25,6 +32,7 @@ const modal = useModalStore();
* @param title
*/
function title(title: string) {
console.log(title);
modal.setTitle(title);
}
@ -74,8 +82,6 @@ function hideModal() {
transform: rotate(135deg);
}
}
}
}
</style>

View File

@ -0,0 +1,236 @@
<template>
<form
@submit="update_playlist"
class="new-p-form"
enctype="multipart/form-data"
>
<label for="name">Playlist name</label>
<br />
<input
type="text"
class="rounded"
name="name"
id="modal-playlist-name-input"
:value="props.playlist.name"
/>
<label for="name">Description</label>
<br />
<textarea
name="description"
id=""
class="rounded"
:value="props.playlist.description"
></textarea>
<br />
<input
type="file"
accept="image/*"
name="image"
id="update-pl-image-upload"
style="display: none"
@change="handleUpload"
/>
<div
id="upload"
class="rounded"
@click="selectFiles"
@dragenter="dragEnter"
@dragover="dragOver"
@drop="drop"
>
<div>Click or Drag an image here</div>
<div
id="update-pl-img-preview"
class="image"
:style="{
backgroundImage: `url(${props.playlist.image})`,
}"
/>
</div>
<input type="submit" class="rounded" value="Update" />
</form>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { Playlist } from "../../interfaces";
import { updatePlaylist } from "../../composables/playlists";
import usePStore from "../../stores/p.ptracks";
const pStore = usePStore();
const props = defineProps<{
playlist: Playlist;
}>();
onMounted(() => {
document.getElementById("modal-playlist-name-input").focus();
});
const emit = defineEmits<{
(e: "title", title: string): void;
(e: "hideModal"): void;
}>();
emit("title", "Update Playlist");
let image: File;
function selectFiles() {
const input = document.getElementById(
"update-pl-image-upload"
) as HTMLInputElement;
input.click();
}
function dragEnter(e: Event) {
e.stopPropagation();
e.preventDefault();
}
function dragOver(e: Event) {
e.stopPropagation();
e.preventDefault();
}
function drop(e: any) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
const dt = e.dataTransfer;
const files = dt.files;
handleFile(files[0]);
}
function handleUpload() {
const input = document.getElementById(
"update-pl-image-upload"
) as HTMLInputElement;
handleFile(input.files[0]);
}
function handleFile(file: File) {
if (!file.type.startsWith("image/")) {
return;
}
const preview = document.getElementById("update-pl-img-preview");
const obj_url = URL.createObjectURL(file);
preview.style.backgroundImage = `url(${obj_url})`;
image = file;
}
function update_playlist(e: Event) {
e.preventDefault();
const form = e.target as HTMLFormElement;
const formData = new FormData(form);
formData.append("image", image);
formData.append("lastUpdated", new Date().toString());
console.log(formData.get("name") == "");
if (formData.get("name").toString().trim() !== "") {
updatePlaylist(props.playlist.playlistid, formData, pStore).then(() => {
emit("hideModal");
});
}
}
</script>
<style lang="scss">
.new-p-form {
grid-gap: 1rem;
margin-top: 1rem;
label {
font-size: 0.9rem;
color: $gray1;
}
input[type="text"] {
margin: $small 0;
border: 2px solid $gray3;
background-color: transparent;
color: #fff;
width: 100%;
padding: 0.5rem;
font-size: 1rem;
&:focus {
border: 2px solid transparent;
outline: solid 2px $gray1;
}
}
input[type="submit"] {
margin: $small 0;
background-color: $accent;
color: #fff;
width: 7rem;
padding: 0.75rem;
font-size: 1rem;
border: none;
outline: none;
cursor: pointer;
}
#upload {
width: 100%;
padding: $small;
border: solid 2px $gray3;
display: grid;
grid-template-columns: 1fr max-content;
place-items: center;
color: $gray1;
margin: $small 0;
cursor: pointer;
#update-pl-img-preview {
width: 4.5rem;
height: 4.5rem;
border-radius: $small;
object-fit: cover;
background-color: $gray4;
}
}
textarea {
width: 100%;
max-width: 28rem;
max-height: 5rem;
color: $white;
background-color: transparent;
border: solid 2px $gray3;
font-family: inherit;
padding: $small;
outline: none;
margin: $small 0;
&:focus {
border: 2px solid transparent;
outline: solid 2px $gray1;
}
}
.colors {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(2rem, 1fr));
grid-gap: 0.5rem;
margin: 0.5rem 0;
.color {
height: 2.5rem;
width: 2.5rem;
border-radius: 2rem;
}
.selected {
border: 4px solid $white;
}
}
}
</style>

View File

@ -1,8 +1,9 @@
import { defineStore } from "pinia";
import { Track } from "../interfaces";
import { Playlist, Track } from "../interfaces";
enum ModalOptions {
newPlaylist,
editPlaylist,
newPlaylist = "newPlaylist",
updatePlaylist = "editPlaylist",
}
export default defineStore("newModal", {
@ -10,7 +11,7 @@ export default defineStore("newModal", {
title: "",
options: ModalOptions,
component: "",
props: {},
props: <any>{},
visible: false,
}),
actions: {
@ -23,6 +24,11 @@ export default defineStore("newModal", {
this.props.track = track;
this.visible = true;
},
showEditPlaylistModal(playlist: Playlist) {
this.component = ModalOptions.updatePlaylist;
this.props = playlist;
this.visible = true;
},
hideModal() {
this.visible = false;
},

View File

@ -13,5 +13,8 @@ export default defineStore("playlist-tracks", {
this.info = playlist.info;
this.tracks = playlist.tracks;
},
updatePInfo(info: Playlist) {
this.info = info;
},
},
});