Files
musicland/src/utils/projectStages.js
T
2025-10-22 17:06:49 +02:00

248 lines
6.5 KiB
JavaScript

import { Routes } from "../navigation/Routes";
export const CREATION_STAGE_KEYS = ["songwriter", "beatmaker", "director"];
const getLyricsCount = (project) => {
if (!project) return 0;
const { lyrics } = project;
return Array.isArray(lyrics) ? lyrics.length : 0;
};
const getStageMetadata = (project) => {
const lyricsCount = getLyricsCount(project);
const hasLyrics = !!(project?.hasLyrics || lyricsCount > 0);
const hasSongUrl = !!project?.songUrl;
const cover = project?.cover || {};
const hasCoverUrl = !!project?.coverUrl;
const hasPlaybackAsset = !!project?.playbackUrl;
const hasPlayback = hasPlaybackAsset || hasSongUrl;
const musicUrls = Array.isArray(project?.musicUrls)
? project.musicUrls.filter(Boolean)
: [];
const musicStatus = project?.musicStatus || null;
const coverStatus = project?.coverStatus || null;
const playbackStatus = project?.playbackStatus || null;
const isPlaybackGenerating =
project?.playbackGenerating === true ||
project?.isPlaybackGenerating === true ||
playbackStatus === "GENERATING";
return {
lyricsCount,
hasLyrics,
hasSongUrl,
hasCover: hasCoverUrl,
hasPlayback,
hasPlaybackAsset,
hasMusicDraft: musicUrls.length > 0,
musicStatus,
coverStatus,
playbackStatus,
isMusicGenerating: musicStatus === "GENERATING",
isCoverGenerating: coverStatus === "GENERATING",
isPlaybackGenerating,
};
};
const getStageLockState = (key, metadata) => {
switch (key) {
case "songwriter":
return metadata.hasSongUrl;
case "beatmaker":
return metadata.lyricsCount <= 0;
case "director":
return !metadata.hasCover;
default:
return true;
}
};
const getStageDescription = (key, metadata) => {
const {
hasLyrics,
hasSongUrl,
hasCover,
hasPlaybackAsset,
hasMusicDraft,
isMusicGenerating,
isPlaybackGenerating,
} = metadata;
switch (key) {
case "songwriter":
if (!hasLyrics) {
return "Commencer à créer des paroles pour votre chanson";
}
if (!hasSongUrl) {
return "Continuer la création de paroles";
}
return "Modifier les paroles créées";
case "beatmaker":
if (!hasLyrics) {
return "Écrivez vos paroles pour débloquer la musique";
}
if (isMusicGenerating) {
return "Votre morceau est en cours de création";
}
if (hasSongUrl) {
if (!hasCover) {
return "Créer ou modifier la cover de votre morceau";
}
return "Modifier la cover ou la production musicale";
}
if (hasMusicDraft) {
return "Modifier la production musicale";
}
return "Commencer la création de votre morceau";
case "director":
if (!hasCover) {
return "Générez une cover pour débloquer le playback";
}
if (isPlaybackGenerating) {
return "Votre playback est en cours de préparation";
}
if (hasPlaybackAsset) {
return "Modifier le playback généré";
}
return "Commencer la création de votre playback";
default:
return "";
}
};
const getStageLockedDescription = (key, metadata) => {
switch (key) {
case "songwriter":
return metadata.hasSongUrl
? "Impossible de modifier les paroles"
: undefined;
case "beatmaker":
return metadata.lyricsCount > 0
? undefined
: "Créez vos paroles pour débloquer le studio";
case "director":
return metadata.hasPlaybackAsset
? "Impossible de modifier le playback"
: undefined;
default:
return undefined;
}
};
const getStageCompletionState = (key, metadata) => {
switch (key) {
case "songwriter":
return metadata.hasLyrics;
case "beatmaker":
return metadata.hasSongUrl || metadata.musicStatus === "GENERATED";
case "director":
return metadata.hasPlaybackAsset;
default:
return false;
}
};
export const getCreationStageStates = (project) => {
const metadata = getStageMetadata(project);
return CREATION_STAGE_KEYS.map((key, index) => {
const isLocked = getStageLockState(key, metadata);
const description = getStageDescription(key, metadata);
const lockedDescription = getStageLockedDescription(key, metadata);
return {
key,
index,
isLocked,
isCompleted: getStageCompletionState(key, metadata),
description:
isLocked && lockedDescription ? lockedDescription : description,
lockedDescription,
};
});
};
export const getStageAction = (key, project) => {
switch (key) {
case "songwriter":
return {
route:
getLyricsCount(project) > 0 ? Routes.Lyrics : Routes.WritingLyrics,
};
case "beatmaker": {
if (!project) {
return { route: Routes.Compose };
}
const musicStatus = project?.musicStatus || null;
const songUrl = project?.songUrl || null;
const coverStatus = project?.coverStatus || null;
const cover = project?.cover || {};
const hasCoverBackground = !!cover?.generatedBackground;
const hasCoverResult = !!cover?.result;
const hasFinalCover = !!project?.coverUrl;
if (musicStatus === "GENERATING") {
return { route: Routes.GeneratingSong };
}
if (!songUrl) {
if (musicStatus === "GENERATED") {
return { route: Routes.SongReady };
}
return { route: Routes.Compose };
}
if (coverStatus === "GENERATING") {
return { route: Routes.PouchReady };
}
if (!hasCoverBackground) {
return { route: Routes.ChooseCoverType };
}
if (!hasCoverResult) {
return { route: Routes.PouchReady };
}
if (!hasFinalCover) {
return { route: Routes.ValidateCover };
}
return { route: Routes.ChooseCoverType };
}
case "director":
return {
route: Routes.Playback,
params: project ? { project } : undefined,
};
default:
return {};
}
};
export const findFirstUnlockedStageIndex = (project) => {
const stages = getCreationStageStates(project);
if (!stages.length) {
return 0;
}
const actionableIndex = stages.findIndex(
(stage) => !stage.isCompleted && !stage.isLocked
);
if (actionableIndex !== -1) {
return actionableIndex;
}
const firstIncomplete = stages.findIndex((stage) => !stage.isCompleted);
if (firstIncomplete !== -1) {
return firstIncomplete;
}
const firstUnlocked = stages.findIndex((stage) => !stage.isLocked);
if (firstUnlocked !== -1) {
return firstUnlocked;
}
return stages.length - 1;
};