Files
krow_talent_app/src/components/krow/proving/MediaChallenge.tsx

78 lines
3.1 KiB
TypeScript

import type { CourseView } from '../types';
import React, { useState } from 'react';
import { Loader2, Camera } from 'lucide-react';
import { base44 } from '@/api/base44Client';
import { Image } from '@/components/ui/image';
import { useTranslation } from 'react-i18next';
// Photo or video proof — capture/upload, then submit for AI evaluation.
interface MediaChallengeProps {
course: CourseView;
onSubmit?: (...args: any[]) => void;
submitting: boolean;
}
export default function MediaChallenge({ course, onSubmit, submitting }: MediaChallengeProps) {
const { t } = useTranslation();
const type = course?.challenge?.type || 'photo';
const [mediaUrl, setMediaUrl] = useState('');
const [uploading, setUploading] = useState(false);
const accept = type === 'video' ? 'video/*' : 'image/*';
const capture = type === 'photo' ? 'environment' : undefined;
const handleFile = async (e) => {
const file = e.target.files?.[0];
if (!file) return;
setUploading(true);
try {
const { file_url } = await base44.integrations.Core.UploadFile({ file });
setMediaUrl(file_url);
} catch {
setMediaUrl('');
} finally {
setUploading(false);
}
};
return (
<div>
<p className="text-[13px] text-ink-3 mb-3">
{type === 'video' ? 'Record or upload a short video demonstrating the challenge.' : 'Take or upload a photo showing your work.'}
</p>
{mediaUrl ? (
<div className="mb-3 rounded-xl overflow-hidden border border-border">
{type === 'video' ? (
<video src={mediaUrl} controls className="w-full max-h-64 object-cover" />
) : (
<Image src={mediaUrl} alt={t('mediaChallenge.yourProof')} className="w-full max-h-64 object-cover" fittingType="fill" />
)}
</div>
) : (
<label className="flex flex-col items-center justify-center h-40 rounded-xl border-2 border-dashed border-border cursor-pointer hover:border-krow-blue transition-colors">
{uploading ? (
<Loader2 className="w-6 h-6 animate-spin text-krow-blue" />
) : (
<>
<Camera className="w-6 h-6 text-ink-4 mb-2" />
<span className="text-[13px] text-ink-3">{t('mediaChallenge.tapTo')} {type === 'video' ? 'record' : 'capture'}</span>
</>
)}
<input type="file" accept={accept} capture={capture} onChange={handleFile} className="hidden" disabled={uploading || submitting} />
</label>
)}
<div className="flex gap-2">
{mediaUrl && (
<button onClick={() => setMediaUrl('')} className="h-10 px-4 rounded-xl border border-border text-[13px] font-medium text-ink-3">{t('mediaChallenge.retake')}</button>
)}
<button
onClick={() => onSubmit(mediaUrl)}
disabled={!mediaUrl || uploading || submitting}
className="flex-1 h-10 rounded-xl bg-krow-navy text-white text-[13px] font-semibold disabled:opacity-40"
>
{t('mediaChallenge.submitProofForAiEvaluation')}
</button>
</div>
</div>
);
}