UI improvements!
This commit is contained in:
parent
3e8141aeba
commit
5c62f9d147
@ -1,8 +1,7 @@
|
|||||||
#root {
|
#root {
|
||||||
max-width: 1280px;
|
max-width: 1280px;
|
||||||
margin: 0 auto;
|
margin: 0;
|
||||||
padding: 2rem;
|
padding: 1rem;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
@ -34,7 +33,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
padding: 2em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.read-the-docs {
|
.read-the-docs {
|
||||||
|
|||||||
@ -56,16 +56,24 @@ export default function RekordboxReader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box p={5}>
|
<Box>
|
||||||
<Heading mb={4}>Rekordbox Reader</Heading>
|
<Flex direction="column" gap={2} mb={4}>
|
||||||
|
<Heading size="md">Rekordbox Reader</Heading>
|
||||||
<Input
|
<Input
|
||||||
type="file"
|
type="file"
|
||||||
accept=".xml"
|
accept=".xml"
|
||||||
onChange={handleFileUpload}
|
onChange={handleFileUpload}
|
||||||
mb={4}
|
size="sm"
|
||||||
|
width="auto"
|
||||||
/>
|
/>
|
||||||
<Flex gap={4}>
|
{songs.length > 0 && (
|
||||||
<Box w="250px">
|
<Button onClick={handleExport} size="sm" colorScheme="blue" width="auto">
|
||||||
|
Export XML
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={4} alignItems="start">
|
||||||
|
<Box w="200px">
|
||||||
<PlaylistManager
|
<PlaylistManager
|
||||||
playlists={playlists}
|
playlists={playlists}
|
||||||
selectedItem={selectedItem}
|
selectedItem={selectedItem}
|
||||||
@ -81,11 +89,6 @@ export default function RekordboxReader() {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
{songs.length > 0 && (
|
|
||||||
<Button onClick={handleExport} mt={4} colorScheme="blue">
|
|
||||||
Export XML
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Input,
|
Input,
|
||||||
Flex,
|
Stack,
|
||||||
Text,
|
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
|
CloseButton,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
@ -12,7 +12,6 @@ import {
|
|||||||
ModalHeader,
|
ModalHeader,
|
||||||
ModalFooter,
|
ModalFooter,
|
||||||
ModalBody,
|
ModalBody,
|
||||||
ModalCloseButton,
|
|
||||||
} from "@chakra-ui/modal";
|
} from "@chakra-ui/modal";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Playlist } from "../types/interfaces";
|
import { Playlist } from "../types/interfaces";
|
||||||
@ -30,23 +29,24 @@ export const PlaylistManager: React.FC<PlaylistManagerProps> = ({
|
|||||||
onPlaylistCreate,
|
onPlaylistCreate,
|
||||||
onPlaylistSelect,
|
onPlaylistSelect,
|
||||||
}) => {
|
}) => {
|
||||||
const disclosure = useDisclosure();
|
const { open, onOpen, onClose } = useDisclosure();
|
||||||
const [newPlaylistName, setNewPlaylistName] = useState("");
|
const [newPlaylistName, setNewPlaylistName] = useState("");
|
||||||
|
|
||||||
const handleCreatePlaylist = () => {
|
const handleCreatePlaylist = () => {
|
||||||
if (newPlaylistName.trim()) {
|
if (newPlaylistName.trim()) {
|
||||||
onPlaylistCreate(newPlaylistName);
|
onPlaylistCreate(newPlaylistName);
|
||||||
setNewPlaylistName("");
|
setNewPlaylistName("");
|
||||||
disclosure.onClose();
|
onClose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Flex direction="column" gap={2}>
|
<Stack gap={2}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => onPlaylistSelect("All Songs")}
|
onClick={() => onPlaylistSelect("All Songs")}
|
||||||
colorScheme={selectedItem === "All Songs" ? "blue" : "gray"}
|
colorScheme={selectedItem === "All Songs" ? "blue" : "gray"}
|
||||||
|
size="sm"
|
||||||
>
|
>
|
||||||
All Songs
|
All Songs
|
||||||
</Button>
|
</Button>
|
||||||
@ -55,32 +55,72 @@ export const PlaylistManager: React.FC<PlaylistManagerProps> = ({
|
|||||||
key={playlist.name}
|
key={playlist.name}
|
||||||
onClick={() => onPlaylistSelect(playlist.name)}
|
onClick={() => onPlaylistSelect(playlist.name)}
|
||||||
colorScheme={selectedItem === playlist.name ? "blue" : "gray"}
|
colorScheme={selectedItem === playlist.name ? "blue" : "gray"}
|
||||||
|
size="sm"
|
||||||
>
|
>
|
||||||
{playlist.name}
|
{playlist.name}
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
<Button onClick={disclosure.onOpen} colorScheme="green">
|
<Button onClick={onOpen} colorScheme="green" size="sm">
|
||||||
Create New Playlist
|
Create New Playlist
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Stack>
|
||||||
|
|
||||||
<Modal isOpen={disclosure.open} onClose={disclosure.onClose}>
|
<Modal
|
||||||
<ModalOverlay />
|
isOpen={open}
|
||||||
<ModalContent>
|
onClose={onClose}
|
||||||
<ModalHeader>Create New Playlist</ModalHeader>
|
isCentered
|
||||||
<ModalCloseButton />
|
motionPreset="slideInBottom"
|
||||||
<ModalBody>
|
>
|
||||||
|
<ModalOverlay
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.4)',
|
||||||
|
backdropFilter: 'blur(2px)'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ModalContent
|
||||||
|
padding={"1rem"}
|
||||||
|
bg="gray.20"
|
||||||
|
bgColor={"rgba(0, 0, 0, 1)"}
|
||||||
|
maxW="500px"
|
||||||
|
w="90%"
|
||||||
|
borderRadius={25}
|
||||||
|
boxShadow={100}
|
||||||
|
margin="0 auto"
|
||||||
|
marginTop="10%"
|
||||||
|
>
|
||||||
|
<ModalHeader color="gray.800" fontSize="lg" fontWeight="bold" pt={6} px={6}>
|
||||||
|
Create New Playlist
|
||||||
|
</ModalHeader>
|
||||||
|
<CloseButton
|
||||||
|
position="absolute"
|
||||||
|
right={'1rem'}
|
||||||
|
top={'1rem'}
|
||||||
|
onClick={onClose}
|
||||||
|
color="gray.600"
|
||||||
|
/>
|
||||||
|
<ModalBody px={6} py={8} paddingTop="2rem">
|
||||||
<Input
|
<Input
|
||||||
value={newPlaylistName}
|
value={newPlaylistName}
|
||||||
onChange={(e) => setNewPlaylistName(e.target.value)}
|
onChange={(e) => setNewPlaylistName(e.target.value)}
|
||||||
placeholder="Playlist name"
|
placeholder="Enter playlist name"
|
||||||
|
autoFocus
|
||||||
|
size="lg"
|
||||||
|
color="gray.800"
|
||||||
|
_placeholder={{ color: 'gray.400' }}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
handleCreatePlaylist();
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter px={6} py={4} borderTop="1px" borderColor="gray.100">
|
||||||
<Button colorScheme="blue" mr={3} onClick={handleCreatePlaylist}>
|
<Button colorScheme="blue" mr={3} onClick={handleCreatePlaylist} size="md" px={8}>
|
||||||
Create
|
Create
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={disclosure.onClose}>Cancel</Button>
|
<Button onClick={onClose} size="md" variant="ghost" color="gray.600">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Box, Flex, Text } from "@chakra-ui/react";
|
import { Box, Flex, Text } from "@chakra-ui/react";
|
||||||
import { Song } from "../types/interfaces";
|
import { Song } from "../types/interfaces";
|
||||||
|
import { ChangeEvent } from "react";
|
||||||
|
|
||||||
interface SongListProps {
|
interface SongListProps {
|
||||||
songs: Song[];
|
songs: Song[];
|
||||||
@ -9,14 +10,23 @@ interface SongListProps {
|
|||||||
|
|
||||||
export const SongList: React.FC<SongListProps> = ({ songs, onAddToPlaylist, playlists }) => {
|
export const SongList: React.FC<SongListProps> = ({ songs, onAddToPlaylist, playlists }) => {
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" gap={4}>
|
<Flex direction="column" gap={2}>
|
||||||
{songs.map((song) => (
|
{songs.map((song) => (
|
||||||
<Box key={song.id} borderWidth="1px" borderRadius="lg" p={4} shadow="md">
|
<Box key={song.id} borderWidth="1px" borderRadius="md" p={2} shadow="sm">
|
||||||
<Text fontWeight="bold">{song.title}</Text>
|
<Flex justify="space-between" align="center">
|
||||||
<Text color="gray.500">{song.artist}</Text>
|
<Box>
|
||||||
|
<Text fontWeight="bold" fontSize="sm">{song.title}</Text>
|
||||||
|
<Text color="gray.500" fontSize="xs">{song.artist}</Text>
|
||||||
|
</Box>
|
||||||
<select
|
<select
|
||||||
onChange={(e) => onAddToPlaylist(song.id, e.target.value)}
|
onChange={(e: ChangeEvent<HTMLSelectElement>) => onAddToPlaylist(song.id, e.target.value)}
|
||||||
value=""
|
value=""
|
||||||
|
style={{
|
||||||
|
padding: '0.25rem',
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
borderRadius: '0.375rem',
|
||||||
|
border: '1px solid #E2E8F0'
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<option value="" disabled>Add to playlist</option>
|
<option value="" disabled>Add to playlist</option>
|
||||||
{playlists.map((playlist) => (
|
{playlists.map((playlist) => (
|
||||||
@ -25,6 +35,7 @@ export const SongList: React.FC<SongListProps> = ({ songs, onAddToPlaylist, play
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@ -24,21 +24,20 @@ a:hover {
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
min-width: 320px;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 3.2em;
|
font-size: 2em;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
padding: 0.6em 1.2em;
|
padding: 0.4em 0.8em;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user