jeanma's picture
Omnilingual ASR transcription demo
ae238b3 verified
import React from "react";
import {useTranscriptionStore} from "../stores/transcriptionStore";
interface QuickGuideProps {
currentStep?: string; // Optional override for current step
}
type GuideStep = {
id: string;
text: string;
icon?: string;
isActive: (state: any) => boolean;
isCompleted: (state: any) => boolean;
};
const QuickGuide: React.FC<QuickGuideProps> = ({currentStep}) => {
const {
file,
transcription,
isLoading,
selectedSegmentIndex,
currentSegments,
currentTime
} = useTranscriptionStore();
// Define all the steps with their conditions
const steps: GuideStep[] = [
{
id: "upload",
text: "Upload or record audio",
icon: "πŸ“",
isActive: (state) => !state.file,
isCompleted: (state) => !!state.file,
},
{
id: "transcribe",
text: "Click transcribe to process",
icon: "🎯",
isActive: (state) =>
!!state.file && !state.transcription && !state.isLoading,
isCompleted: (state) => !!state.transcription || state.isLoading,
},
{
id: "play",
text: "Play media",
icon: "▢️",
isActive: (state) => !!state.transcription,
isCompleted: () => (currentTime ?? 0) > 0, // Always in progress when transcription available
},
// {
// id: "jump",
// text: "Click segments to jump",
// icon: "🎡",
// isActive: (state) => !!state.transcription,
// isCompleted: () => false, // Always in progress when transcription available
// },
// {
// id: "drag",
// text: "Drag segments to move/resize",
// icon: "↔️",
// isActive: (state) => !!state.transcription,
// isCompleted: () => false, // Always in progress when transcription available
// },
// {
// id: "combine",
// text: "Use slider to combine segments",
// icon: "πŸ”—",
// isActive: (state) => !!state.transcription,
// isCompleted: () => false, // Always in progress when transcription available
// },
// {
// id: "download",
// text: "Download subtitles",
// icon: "πŸ’Ύ",
// isActive: (state) => !!state.transcription,
// isCompleted: () => false, // Always in progress when transcription available
// },
];
// Create state object for condition checking
const storeState = {
file,
transcription,
isLoading,
selectedSegmentIndex,
currentSegments,
};
// Determine step states
const getStepState = (step: GuideStep) => {
// Override with currentStep prop if provided
if (currentStep) {
if (step.id === currentStep) return "active";
if (step.isCompleted(storeState)) return "completed";
return "inactive";
}
// Default logic based on store state
if (step.isCompleted(storeState)) return "completed";
if (step.isActive(storeState)) return "active";
return "inactive";
};
// Get the appropriate CSS classes for each step state
const getStepClasses = (stepState: string) => {
switch (stepState) {
case "active":
return "text-blue-300 bg-blue-900/30 border-blue-500/50 font-medium";
case "completed":
return "text-green-300 bg-green-900/20 border-green-500/30";
default:
return "text-gray-400 bg-transparent border-transparent";
}
};
// Get icon for step state
const getStepIcon = (step: GuideStep, stepState: string) => {
if (stepState === "completed") return "βœ“";
if (stepState === "active") return "β†’";
return step.icon || "β€’";
};
return (
<div className="border-t border-gray-700 py-3">
<h3 className="text-xs font-semibold mb-2 text-gray-200">Quick Guide</h3>
<div className="space-y-1">
{steps.map((step) => {
const stepState = getStepState(step);
const stepClasses = getStepClasses(stepState);
const icon = getStepIcon(step, stepState);
return (
<div
key={step.id}
className={`text-xs px-2 py-1 rounded border transition-all duration-200 ${stepClasses}`}
>
<span
className="inline-block w-4 text-center mr-1"
aria-label={`Step ${step.id}`}
>
{icon}
</span>
{step.text}
</div>
);
})}
</div>
{/* Progress indicator */}
{transcription && (
<div className="mt-2 pt-2 border-t border-gray-600">
<div className="text-xs text-gray-400">
{selectedSegmentIndex !== null ? (
<span className="text-yellow-400">✏️ Editing mode active</span>
) : (
<span className="text-green-400">
βœ“ Ready for playback & editing
</span>
)}
</div>
</div>
)}
{/* Loading indicator */}
{isLoading && (
<div className="mt-2 pt-2 border-t border-gray-600">
<div className="text-xs text-blue-400 animate-pulse">
⏳ Processing... Please wait
</div>
</div>
)}
</div>
);
};
export default QuickGuide;