working team update/create (still need enroll)
This commit is contained in:
@@ -1,56 +1,149 @@
|
||||
import { SlidePanelField } from "@/components/sheet/slide-panel";
|
||||
import { Stack, Text } from "@mantine/core";
|
||||
import { Stack, Text, Group, Avatar } from "@mantine/core";
|
||||
import { UseFormReturnType } from "@mantine/form";
|
||||
import { TeamInput } from "../../types";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useMemo } from "react";
|
||||
import { SpotifyTrack } from "@/lib/spotify/types";
|
||||
import SongSearch from "./song-search";
|
||||
import DurationPicker from "./duration-picker";
|
||||
import SongSummary from "./song-summary";
|
||||
import { MusicNote } from "@phosphor-icons/react/dist/ssr";
|
||||
|
||||
interface Song {
|
||||
song_id: string;
|
||||
song_name: string;
|
||||
song_artist: string;
|
||||
song_album: string;
|
||||
song_year?: number;
|
||||
song_start?: number;
|
||||
song_end?: number;
|
||||
song_image_url: string;
|
||||
}
|
||||
|
||||
interface SongPickerProps {
|
||||
form: UseFormReturnType<TeamInput>
|
||||
form: UseFormReturnType<TeamInput>;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
const SongPicker = ({ form }: SongPickerProps) => {
|
||||
const [song, setSong] = useState<Song>();
|
||||
|
||||
useEffect(() => {
|
||||
const SongPicker = ({ form, error }: SongPickerProps) => {
|
||||
const currentSong = useMemo((): Song | undefined => {
|
||||
const values = form.getValues();
|
||||
|
||||
setSong({
|
||||
song_id: values.song_id || "",
|
||||
song_name: values.song_name || "",
|
||||
song_artist: values.song_artist || "",
|
||||
song_album: values.song_album || "",
|
||||
song_year: values.song_year,
|
||||
song_start: values.song_start,
|
||||
song_end: values.song_end,
|
||||
song_image_url: values.song_image_url || "",
|
||||
})
|
||||
}, []);
|
||||
if (values.song_id && values.song_name) {
|
||||
return {
|
||||
song_id: values.song_id,
|
||||
song_name: values.song_name,
|
||||
song_artist: values.song_artist || "",
|
||||
song_album: values.song_album || "",
|
||||
song_start: values.song_start,
|
||||
song_end: values.song_end,
|
||||
song_image_url: values.song_image_url || "",
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}, [form.values.song_id, form.values.song_name, form.values.song_artist, form.values.song_album, form.values.song_image_url, form.values.song_start, form.values.song_end]);
|
||||
|
||||
return (
|
||||
<SlidePanelField
|
||||
key={"song-picker"}
|
||||
value={""}
|
||||
onChange={console.log}
|
||||
Component={() => (
|
||||
<Stack>
|
||||
<Text>Song picker</Text>
|
||||
</Stack>
|
||||
)}
|
||||
value={currentSong}
|
||||
formatValue={(song) => <SongSummary song={song} />}
|
||||
onChange={(updatedSong: Song) => {
|
||||
if (updatedSong) {
|
||||
form.setValues({
|
||||
song_id: updatedSong.song_id,
|
||||
song_name: updatedSong.song_name,
|
||||
song_artist: updatedSong.song_artist,
|
||||
song_album: updatedSong.song_album,
|
||||
song_start: updatedSong.song_start,
|
||||
song_end: updatedSong.song_end,
|
||||
song_image_url: updatedSong.song_image_url,
|
||||
});
|
||||
}
|
||||
}}
|
||||
error={error}
|
||||
Component={SongPickerComponent}
|
||||
componentProps={{ formValues: form.getValues() }}
|
||||
title={"Select Song"}
|
||||
label={"Song"}
|
||||
label={"Walkout Song"}
|
||||
placeholder={"Select your walkout song"}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
interface SongPickerComponentProps {
|
||||
value: Song | undefined;
|
||||
onChange: (song: Song) => void;
|
||||
formValues: any;
|
||||
}
|
||||
|
||||
const SongPickerComponent = ({ value: song, onChange, formValues }: SongPickerComponentProps) => {
|
||||
const handleSongSelect = (track: SpotifyTrack) => {
|
||||
const defaultStart = 0;
|
||||
const defaultEnd = Math.min(15, Math.floor(track.duration_ms / 1000));
|
||||
|
||||
const newSong: Song = {
|
||||
song_id: track.id,
|
||||
song_name: track.name,
|
||||
song_artist: track.artists.map(a => a.name).join(', '),
|
||||
song_album: track.album.name,
|
||||
song_image_url: track.album.images[0]?.url || '',
|
||||
song_start: defaultStart,
|
||||
song_end: defaultEnd,
|
||||
};
|
||||
|
||||
onChange(newSong);
|
||||
};
|
||||
|
||||
const handleDurationChange = (startSeconds: number, endSeconds: number) => {
|
||||
if (song) {
|
||||
onChange({
|
||||
...song,
|
||||
song_start: startSeconds,
|
||||
song_end: endSeconds,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack styles={{ root: { width: '100%' }}}>
|
||||
<Text size="lg" fw={500}>Search for a Song</Text>
|
||||
|
||||
<SongSearch onChange={handleSongSelect} />
|
||||
|
||||
<Stack gap="lg" mt="md">
|
||||
<Group gap="sm">
|
||||
<Avatar
|
||||
src={song?.song_image_url || null}
|
||||
size={60}
|
||||
radius="md"
|
||||
bg="transparent"
|
||||
>
|
||||
{!song?.song_image_url && <MusicNote size={24} color="var(--mantine-color-dimmed)" />}
|
||||
</Avatar>
|
||||
<div>
|
||||
<Text size="sm" fw={500} c={song?.song_name ? undefined : "dimmed"}>
|
||||
{song?.song_name || "No song selected"}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
{song?.song_artist || "Select a song to see details"}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
{song?.song_album || ""}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
|
||||
<Stack gap="xs">
|
||||
<DurationPicker
|
||||
songDurationMs={180000}
|
||||
initialStart={song?.song_start || 0}
|
||||
initialEnd={song?.song_end || 15}
|
||||
onChange={handleDurationChange}
|
||||
disabled={!song?.song_id}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SongPicker;
|
||||
Reference in New Issue
Block a user