jam-cloud/jam-ui/src/components/jamtracks/JKCreateCustomMix.js

253 lines
8.0 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { Table, Row, Col, Input, Button } from 'reactstrap';
import JKInstrumentIcon from '../profile/JKInstrumentIcon';
import Select from 'react-select';
import { useForm, Controller } from 'react-hook-form';
import { createMixdown } from '../../helpers/rest';
const JKCreateCustomMix = ({ jamTrack }) => {
const [tracks, setTracks] = useState([]);
//const [selectedTracks, setSelectedTracks] = useState([]);
const TEMPO_OPTIONS = [
{ value: '0', label: 'Original tempo' },
{ value: '-5', label: 'Slower by 5%' },
{ value: '-10', label: 'Slower by 10%' },
{ value: '-15', label: 'Slower by 15%' },
{ value: '-20', label: 'Slower by 20%' },
{ value: '-25', label: 'Slower by 25%' },
{ value: '-30', label: 'Slower by 30%' },
{ value: '-35', label: 'Slower by 35%' },
{ value: '-40', label: 'Slower by 40%' },
{ value: '-45', label: 'Slower by 45%' },
{ value: '-50', label: 'Slower by 50%' },
{ value: '-60', label: 'Slower by 60%' },
{ value: '-70', label: 'Slower by 70%' },
{ value: '-80', label: 'Slower by 80%' },
{ value: '5', label: 'Faster by 5%' },
{ value: '10', label: 'Faster by 10%' },
{ value: '15', label: 'Faster by 15%' },
{ value: '20', label: 'Faster by 20%' },
{ value: '30', label: 'Faster by 30%' },
{ value: '40', label: 'Faster by 40%' },
{ value: '50', label: 'Faster by 50%' }
];
const PITCH_OPTIONS = [
{ value: '0', label: 'Original pitch' },
{ value: '-1', label: 'Down 1 semitone' },
{ value: '-2', label: 'Down 2 semitone' },
{ value: '-3', label: 'Down 3 semitone' },
{ value: '-4', label: 'Down 4 semitone' },
{ value: '-5', label: 'Down 5 semitone' },
{ value: '-6', label: 'Down 6 semitone' },
{ value: '-7', label: 'Down 7 semitone' },
{ value: '-8', label: 'Down 8 semitone' },
{ value: '-9', label: 'Down 9 semitone' },
{ value: '-10', label: 'Down 10 semitone' },
{ value: '-11', label: 'Down 11 semitone' },
{ value: '-12', label: 'Down 12 semitone' },
{ value: '1', label: 'Up 1 semitone' },
{ value: '2', label: 'Up 2 semitone' },
{ value: '3', label: 'Up 3 semitone' },
{ value: '4', label: 'Up 4 semitone' },
{ value: '5', label: 'Up 5 semitone' },
{ value: '6', label: 'Up 6 semitone' },
{ value: '7', label: 'Up 7 semitone' },
{ value: '8', label: 'Up 8 semitone' },
{ value: '9', label: 'Up 9 semitone' },
{ value: '10', label: 'Up 10 semitone' },
{ value: '11', label: 'Up 11 semitone' },
{ value: '12', label: 'Up 12 semitone' }
];
const {
control,
handleSubmit,
formState: { errors },
setValue,
getValues
} = useForm({
defaultValues: {
mixName: '',
tempo: {
value: '0',
label: 'Original tempo'
},
pitch: {
value: '0',
label: 'Original pitch'
},
mixdownTracks: []
}
});
const onSubmit = data => {
console.log('data', data);
const _tracks = [];
let countIn = false;
const selectedTracks = getValues('mixdownTracks');
tracks.forEach(track => {
const muted = selectedTracks.includes(track.id);
if (track.id === 'count-in') {
if (countIn === false) {
countIn = !muted;
}
} else {
_tracks.push({
id: track.id,
mute: selectedTracks.includes(track.id)
});
}
});
setValue('mixdownTracks', _tracks);
const mixData = {
jamTrackID: jamTrack.id,
name: data.mixName,
settings: { speed: data.tempo.value, pitch: data.pitch.value, 'count-in': countIn, tracks: _tracks }
};
console.log('mixData', mixData);
createMixdown(mixData)
.then(response => {
console.log('mixdown created', response);
//TODO: add this mixdown to global state of jamtrack mixdowns
})
.catch(error => {
console.error('mixdown create error', error);
});
};
const toggleTrack = e => {
const trackId = e.target.value;
const selectedTracks = getValues('mixdownTracks');
if (selectedTracks.includes(trackId)) {
//setSelectedTracks(selectedTracks.filter(track => track !== trackId));
setValue('mixdownTracks', selectedTracks.filter(track => track !== trackId));
} else {
//setSelectedTracks([...selectedTracks, trackId]);
setValue('mixdownTracks', [...selectedTracks, trackId]);
}
};
useEffect(() => {
if (jamTrack) {
setTracks(jamTrack.tracks.filter(track => track.track_type === 'Track' || track.track_type === 'Click'));
}
}, [jamTrack]);
const trackName = track => {
if (track.track_type === 'Track' || track.track_type === 'Click') {
if (track.track_type === 'Click') {
return 'Clicktrack';
} else if (track.instrument) {
const instrumentDescription = track.instrument.description;
let part = '';
if (track.part && track.part !== instrumentDescription) {
part = `(${track.part})`;
}
return `${instrumentDescription} ${part}`;
}
}
};
return (
<>
<p>
Mute any tracks you like. Adjust the pitch or tempo of playback. Then give your mix a descriptive name, and
click the Create Mix button. It will take few minutes for us to create your custom mix.
</p>
<form onSubmit={handleSubmit(onSubmit)}>
<Row>
<Col>
<Table striped bordered className="fs--1">
<thead className="bg-200 text-900">
<tr>
<th>Tracks {tracks.length > 0 && <>({tracks.length})</>}</th>
<th>Mute</th>
</tr>
</thead>
<tbody>
{tracks &&
tracks.map((track, index) => (
<tr key={index}>
<td>
<JKInstrumentIcon instrumentId={track.instrumentId} instrumentName={trackName(track)} />
<span className="ml-1">{trackName(track)}</span>
</td>
<td>
<input type="checkbox" value={track.id} onClick={toggleTrack} />
</td>
</tr>
))}
</tbody>
</Table>
<Controller
name="mixdownTracks"
control={control}
rules={{
required: 'Select at least one track to create a mix'
}}
render={({ field }) => <Input type='hidden' {...field} />}
/>
{errors.mixdownTracks && (
<div className="text-danger">
<small>{errors.mixdownTracks.message}</small>
</div>
)}
</Col>
</Row>
<Row className="mb-1">
<Col>Tempo</Col>
<Col>
<Controller
name="tempo"
control={control}
render={({ field }) => <Select {...field} options={TEMPO_OPTIONS} />}
/>
</Col>
</Row>
<Row className="mb-1">
<Col>Pitch</Col>
<Col>
<Controller
name="pitch"
control={control}
render={({ field }) => <Select {...field} options={PITCH_OPTIONS} />}
/>
</Col>
</Row>
<Row className="mb-1">
<Col>Mix Name</Col>
<Col>
<Controller
name="mixName"
control={control}
rules={{
required: 'Mix name is required'
}}
render={({ field }) => <Input {...field} />}
/>
{errors.mixName && (
<div className="text-danger">
<small>{errors.mixName.message}</small>
</div>
)}
</Col>
</Row>
<Row>
<Col>
<Button>Create Mix</Button>
</Col>
</Row>
</form>
</>
);
};
export default JKCreateCustomMix;