diff --git a/packages/app/src/components/Creator/creators/playlist/index.jsx b/packages/app/src/components/Creator/creators/playlist/index.jsx
index 9ccd2535..836998aa 100644
--- a/packages/app/src/components/Creator/creators/playlist/index.jsx
+++ b/packages/app/src/components/Creator/creators/playlist/index.jsx
@@ -1,12 +1,293 @@
import React from "react"
import * as antd from "antd"
-import { Icons, createIconRender } from "components/Icons"
+import { Icons } from "components/Icons"
import "./index.less"
+const UploadHint = (props) => {
+ return
+
+
Upload your tracks
+
Drag and drop your tracks here or click this box to start uploading files.
+
+}
+
+// TODO: Handle `cntr+v` to paste data from the clipboard to the post additions
+// TODO: Send file deletion request to the server when user removes file from the list
+// TODO: Make cover preview style more beautiful (E.G. Use the entire div as background)
+// TODO: Make files list item can be dragged to change their order
+// TODO: Make files can be modified (E.G. Change cover, change title, change artist, etc.)
+
export default (props) => {
+ const api = app.api.withEndpoints("main")
+
+ const [playlistName, setPlaylistName] = React.useState(null)
+ const [playlistDescription, setPlaylistDescription] = React.useState(null)
+ const [playlistArtist, setPlaylistArtist] = React.useState(null)
+ const [coverURL, setCoverURL] = React.useState(null)
+ const [fileList, setFileList] = React.useState([])
+
+ const [pending, setPending] = React.useState([])
+ const [loading, setLoading] = React.useState(false)
+
+ const handleTitleOnChange = (event) => {
+ const value = event.target.value
+
+ if (value === "") {
+ return setPlaylistName(null)
+ }
+
+ return setPlaylistName(event.target.value)
+ }
+
+ const handleDescriptionOnChange = (event) => {
+ const value = event.target.value
+
+ if (value === "") {
+ return setPlaylistDescription(null)
+ }
+
+ return setPlaylistDescription(event.target.value)
+ }
+
+ const handleArtistOnChange = (event) => {
+ const value = event.target.value
+
+ if (value === "") {
+ return setPlaylistArtist(null)
+ }
+
+ return setPlaylistArtist(event.target.value)
+ }
+
+ const handleUploaderOnChange = (change) => {
+ switch (change.file.status) {
+ case "uploading": {
+ setPending([...pending, change.file.uid])
+ break
+ }
+ case "done": {
+ const recivedFiles = []
+
+ // remove pending file
+ setPending(pending.filter(uid => uid !== change.file.uid))
+
+ // push to file list
+ if (Array.isArray(change.file.response)) {
+ recivedFiles.push(...change.file.response)
+ } else {
+ recivedFiles.push(change.file.response)
+ }
+
+ // add uid to files
+ recivedFiles.forEach((file) => {
+ file.uid = change.file.uid
+ })
+
+ setFileList([...fileList, ...recivedFiles])
+
+ break
+ }
+ case "removed": {
+ // remove from file list
+ setFileList(fileList.filter(file => file.uid !== change.file.uid))
+ }
+
+ default: {
+ break
+ }
+ }
+ }
+
+ const handleCoverUploaderOnChange = (change) => {
+ switch (change.file.status) {
+ case "uploading": {
+ setPending([...pending, change.file.uid])
+ break
+ }
+ case "done": {
+ // remove pending file
+ setPending(pending.filter(uid => uid !== change.file.uid))
+
+ setCoverURL(change.file.response[0].url)
+
+ break
+ }
+ case "removed": {
+ setCoverURL(null)
+ }
+
+ default: {
+ break
+ }
+ }
+ }
+
+ const handleUpload = async (req) => {
+ // get file data
+ const file = req.file
+
+ // append to form data
+ const formData = new FormData()
+ formData.append("files", file)
+
+ // send request
+ const request = await api.post.upload(formData, undefined).catch((error) => {
+ console.error(error)
+ antd.message.error(error)
+ req.onError(error)
+
+ return false
+ })
+
+ if (request) {
+ return req.onSuccess(request)
+ }
+ }
+
+ const checkCanSubmit = () => {
+ const nameValid = playlistName !== null && playlistName.length !== 0
+ const filesListValid = fileList.length !== 0
+ const isPending = pending.length !== 0
+
+ return nameValid && filesListValid && !isPending
+ }
+
+ const handleSubmit = async () => {
+ setLoading(true)
+
+ let RequestData = {
+ type: "playlist",
+ message: playlistDescription,
+ data: {
+ title: playlistName,
+ cover: coverURL,
+ artist: playlistArtist,
+ playlist: fileList.map((file) => {
+ return {
+ title: file.name,
+ cover: file.cover ?? coverURL,
+ artist: file.artist ?? "Unknown",
+ src: file.url,
+ }
+ })
+ }
+ }
+
+ const response = api.post.post(RequestData).catch(error => {
+ console.error(error)
+ antd.message.error(error)
+
+ return false
+ })
+
+ setLoading(false)
+
+ if (response) {
+ if (typeof props.close === "function") {
+ props.close()
+ }
+ }
+ }
+
return
-
+
+
+
+
+
+
+ {
+ coverURL &&
+

+
{
+ setCoverURL(null)
+ }}
+ icon={}
+ shape="round"
+ >
+ Remove Cover
+
+
+ }
+ {
+ !coverURL &&
+ }>Upload cover
+
+ }
+
+
+
+
+ {fileList.length === 0 ? : }>
+ Upload files
+ }
+
+
+
+
+
}
+ loading={loading}
+ onClick={handleSubmit}
+ >
+ Publish
+
+
+
+
+
}
\ No newline at end of file
diff --git a/packages/app/src/components/Creator/creators/playlist/index.less b/packages/app/src/components/Creator/creators/playlist/index.less
index d061c844..240d0574 100644
--- a/packages/app/src/components/Creator/creators/playlist/index.less
+++ b/packages/app/src/components/Creator/creators/playlist/index.less
@@ -1,3 +1,121 @@
.playlistCreator {
-
+ display: flex;
+ flex-direction: column;
+
+ align-items: center;
+ justify-content: center;
+
+ width: 100%;
+
+ .inputField {
+ display: inline-flex;
+ flex-direction: row;
+
+ align-self: start;
+ align-items: center;
+ justify-content: flex-start;
+
+ width: 100%;
+
+ margin-bottom: 20px;
+
+ font-size: 2rem;
+
+ .inputText {
+ width: 100%;
+ }
+
+ .coverUploader {
+ width: 100px;
+ }
+
+ .coverPreview {
+ height: 5vh;
+
+ img {
+ height: 100%;
+ border-radius: 10px;
+ margin-right: 10px;
+ }
+
+ svg {
+ margin: 0!important;
+ }
+ }
+ }
+
+ .files {
+ display: flex;
+ flex-direction: column;
+
+ align-items: center;
+ justify-content: center;
+
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+
+ width: 100%;
+ height: 100%;
+
+ padding: 10px;
+ margin-bottom: 20px;
+
+ .uploader,
+ .ant-upload {
+ display: flex;
+ flex-direction: column;
+
+ align-items: center;
+ justify-content: center;
+
+ width: 100%;
+ }
+
+ .ant-upload-list,
+ .ant-upload-list-picture-container {
+ width: 100%;
+ }
+
+ .ant-upload-list-item-thumbnail {
+ display: inline-flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .ant-upload-list-item {
+ display: inline-flex;
+ flex-direction: row;
+
+ align-items: center;
+ justify-content: space-between;
+
+ width: 100%;
+ }
+ }
+
+ .uploadHint {
+ display: flex;
+ flex-direction: column;
+
+ align-self: center;
+ align-items: center;
+ justify-content: center;
+
+ width: 100%;
+ height: 100%;
+
+ svg {
+ font-size: 3rem;
+ }
+
+ h3 {
+ font-size: 1.5rem;
+ }
+ }
+
+ .footer {
+ position: relative;
+ padding: 10px;
+ }
}
\ No newline at end of file