refactor: change video activity modal UI

This commit is contained in:
swve 2025-04-22 15:53:02 +02:00
parent ed8783d0ef
commit 3173e6b417
7 changed files with 221 additions and 214 deletions

View file

@ -3,17 +3,42 @@ import YouTube from 'react-youtube'
import { getActivityMediaDirectory } from '@services/media/media'
import { useOrg } from '@components/Contexts/OrgContext'
function VideoActivity({ activity, course }: { activity: any; course: any }) {
interface VideoActivityProps {
activity: {
activity_sub_type: string
activity_uuid: string
content: {
filename?: string
uri?: string
}
}
course: {
course_uuid: string
}
}
function VideoActivity({ activity, course }: VideoActivityProps) {
const org = useOrg() as any
const [videoId, setVideoId] = React.useState('')
React.useEffect(() => {
if (activity && activity.content && activity.content.uri) {
var getYouTubeID = require('get-youtube-id');
if (activity?.content?.uri) {
var getYouTubeID = require('get-youtube-id')
setVideoId(getYouTubeID(activity.content.uri))
}
}, [activity, org])
const getVideoSrc = () => {
if (!activity.content?.filename) return ''
return getActivityMediaDirectory(
org?.org_uuid,
course?.course_uuid,
activity.activity_uuid,
activity.content.filename,
'video'
)
}
return (
<div className="w-full max-w-full px-2 sm:px-4">
{activity && (
@ -24,13 +49,7 @@ function VideoActivity({ activity, course }: { activity: any; course: any }) {
<video
className="w-full h-full object-cover"
controls
src={getActivityMediaDirectory(
org?.org_uuid,
course?.course_uuid,
activity.activity_uuid,
activity.content?.filename,
'video'
)}
src={getVideoSrc()}
></video>
</div>
</div>
@ -44,7 +63,7 @@ function VideoActivity({ activity, course }: { activity: any; course: any }) {
width: '100%',
height: '100%',
playerVars: {
autoplay: 0,
autoplay: 0
},
}}
videoId={videoId}

View file

@ -4,11 +4,11 @@ import VideoPageActivityImage from 'public//activities_types/video-page-activity
import DocumentPdfPageActivityImage from 'public//activities_types/documentpdf-page-activity.png'
import AssignmentActivityImage from 'public//activities_types/assignment-page-activity.png'
import DynamicCanvaModal from './NewActivityModal/DynamicCanva'
import VideoModal from './NewActivityModal/Video'
import DynamicCanvaModal from './NewActivityModal/DynamicActivityModal'
import VideoModal from './NewActivityModal/VideoActivityModal'
import Image from 'next/image'
import DocumentPdfModal from './NewActivityModal/DocumentPdf'
import Assignment from './NewActivityModal/Assignment'
import DocumentPdfModal from './NewActivityModal/DocumentActivityModal'
import Assignment from './NewActivityModal/AssignmentActivityModal'
function NewActivityModal({
closeModal,

View file

@ -1,199 +0,0 @@
import FormLayout, {
ButtonBlack,
Flex,
FormField,
FormLabel,
FormMessage,
Input,
} from '@components/Objects/StyledElements/Form/Form'
import React, { useState } from 'react'
import * as Form from '@radix-ui/react-form'
import BarLoader from 'react-spinners/BarLoader'
import { Youtube } from 'lucide-react'
import { constructAcceptValue } from '@/lib/constants';
const SUPPORTED_FILES = constructAcceptValue(['mp4', 'webm'])
interface ExternalVideoObject {
name: string
type: string
uri: string
chapter_id: string
}
function VideoModal({
submitFileActivity,
submitExternalVideo,
chapterId,
course,
}: any) {
const [video, setVideo] = React.useState(null) as any
const [isSubmitting, setIsSubmitting] = useState(false)
const [name, setName] = React.useState('')
const [youtubeUrl, setYoutubeUrl] = React.useState('')
const [selectedView, setSelectedView] = React.useState('file') as any
const handleVideoChange = (event: React.ChangeEvent<any>) => {
setVideo(event.target.files[0])
}
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value)
}
const handleYoutubeUrlChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
setYoutubeUrl(event.target.value)
}
const handleSubmit = async (e: any) => {
e.preventDefault()
setIsSubmitting(true)
if (selectedView === 'file') {
let status = await submitFileActivity(
video,
'video',
{
name: name,
chapter_id: chapterId,
activity_type: 'TYPE_VIDEO',
activity_sub_type: 'SUBTYPE_VIDEO_HOSTED',
published_version: 1,
version: 1,
course_id: course.id,
},
chapterId
)
setIsSubmitting(false)
}
if (selectedView === 'youtube') {
let external_video_object: ExternalVideoObject = {
name,
type: 'youtube',
uri: youtubeUrl,
chapter_id: chapterId,
}
let status = await submitExternalVideo(
external_video_object,
'activity',
chapterId
)
setIsSubmitting(false)
}
}
/* TODO : implement some sort of progress bar for file uploads, it is not possible yet because i'm not using axios.
and the actual upload isn't happening here anyway, it's in the submitFileActivity function */
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="video-activity-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Video name</FormLabel>
<FormMessage match="valueMissing">
Please provide a name for your video activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Input onChange={handleNameChange} type="text" required />
</Form.Control>
</FormField>
<div className="flex flex-col rounded-md bg-gray-50 outline-dashed outline-gray-200">
<div className="">
<div className="flex m-4 justify-center space-x-2 mb-0">
<div
onClick={() => {
setSelectedView('file')
}}
className="rounded-full bg-slate-900 text-zinc-50 py-2 px-4 text-sm drop-shadow-md hover:cursor-pointer hover:bg-slate-700 "
>
Video upload
</div>
<div
onClick={() => {
setSelectedView('youtube')
}}
className="rounded-full bg-slate-900 text-zinc-50 py-2 px-4 text-sm drop-shadow-md hover:cursor-pointer hover:bg-slate-700"
>
YouTube Video
</div>
</div>
{selectedView === 'file' && (
<div className="p-4 justify-center m-auto align-middle">
<FormField name="video-activity-file">
<Flex
css={{
alignItems: 'baseline',
justifyContent: 'space-between',
}}
>
<FormLabel>Video file</FormLabel>
<FormMessage match="valueMissing">
Please provide a video for your activity
</FormMessage>
</Flex>
<Form.Control asChild>
<input accept={SUPPORTED_FILES} type="file" onChange={handleVideoChange} required />
</Form.Control>
</FormField>
</div>
)}
{selectedView === 'youtube' && (
<div className="p-4 justify-center m-auto align-middle">
<FormField name="video-activity-file">
<Flex
css={{
alignItems: 'baseline',
justifyContent: 'space-between',
}}
>
<FormLabel className="flex justify-center align-middle">
<Youtube className="m-auto pr-1" />
<span className="flex">YouTube URL</span>
</FormLabel>
<FormMessage match="valueMissing">
Please provide a video for your activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Input
className="bg-white"
onChange={handleYoutubeUrlChange}
type="text"
required
/>
</Form.Control>
</FormField>
</div>
)}
</div>
</div>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack
className="bg-black"
type="submit"
css={{ marginTop: 10 }}
>
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Create activity'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
)
}
export default VideoModal

View file

@ -0,0 +1,187 @@
import FormLayout, {
ButtonBlack,
Flex,
FormField,
FormLabel,
FormMessage,
Input,
} from '@components/Objects/StyledElements/Form/Form'
import React, { useState } from 'react'
import * as Form from '@radix-ui/react-form'
import BarLoader from 'react-spinners/BarLoader'
import { Youtube, Upload } from 'lucide-react'
import { constructAcceptValue } from '@/lib/constants'
const SUPPORTED_FILES = constructAcceptValue(['mp4', 'webm'])
interface ExternalVideoObject {
name: string
type: string
uri: string
chapter_id: string
}
function VideoModal({
submitFileActivity,
submitExternalVideo,
chapterId,
course,
}: any) {
const [video, setVideo] = React.useState<File | null>(null)
const [isSubmitting, setIsSubmitting] = useState(false)
const [name, setName] = React.useState('')
const [youtubeUrl, setYoutubeUrl] = React.useState('')
const [selectedView, setSelectedView] = React.useState<'file' | 'youtube'>('file')
const handleVideoChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files?.[0]) {
setVideo(event.target.files[0])
}
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setIsSubmitting(true)
try {
if (selectedView === 'file' && video) {
await submitFileActivity(
video,
'video',
{
name: name,
chapter_id: chapterId,
activity_type: 'TYPE_VIDEO',
activity_sub_type: 'SUBTYPE_VIDEO_HOSTED',
published_version: 1,
version: 1,
course_id: course.id,
},
chapterId
)
}
if (selectedView === 'youtube') {
const external_video_object: ExternalVideoObject = {
name,
type: 'youtube',
uri: youtubeUrl,
chapter_id: chapterId,
}
await submitExternalVideo(
external_video_object,
'activity',
chapterId
)
}
} finally {
setIsSubmitting(false)
}
}
return (
<FormLayout onSubmit={handleSubmit}>
<FormField name="video-activity-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Activity Name</FormLabel>
<FormMessage match="valueMissing">
Please provide a name for your video activity
</FormMessage>
</Flex>
<Form.Control asChild>
<Input
value={name}
onChange={(e) => setName(e.target.value)}
type="text"
required
placeholder="Enter activity name..."
/>
</Form.Control>
</FormField>
<div className="mt-4 rounded-lg border border-gray-200">
<div className="grid grid-cols-2 gap-0">
<button
type="button"
onClick={() => setSelectedView('file')}
className={`flex items-center justify-center p-4 gap-2 ${
selectedView === 'file'
? 'bg-gray-100 border-b-2 border-black'
: 'hover:bg-gray-50 border-b border-gray-200'
}`}
>
<Upload size={18} />
<span>Upload Video</span>
</button>
<button
type="button"
onClick={() => setSelectedView('youtube')}
className={`flex items-center justify-center p-4 gap-2 ${
selectedView === 'youtube'
? 'bg-gray-100 border-b-2 border-black'
: 'hover:bg-gray-50 border-b border-gray-200'
}`}
>
<Youtube size={18} />
<span>YouTube Video</span>
</button>
</div>
<div className="p-6">
{selectedView === 'file' && (
<div className="space-y-4">
<FormField name="video-activity-file">
<FormLabel>Video File</FormLabel>
<div className="mt-2">
<input
type="file"
accept={SUPPORTED_FILES}
onChange={handleVideoChange}
required
className="w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-black file:text-white hover:file:bg-gray-800"
/>
</div>
</FormField>
</div>
)}
{selectedView === 'youtube' && (
<div className="space-y-4">
<FormField name="youtube-url">
<FormLabel>YouTube URL</FormLabel>
<Form.Control asChild>
<Input
value={youtubeUrl}
onChange={(e) => setYoutubeUrl(e.target.value)}
type="text"
required
placeholder="https://youtube.com/watch?v=..."
/>
</Form.Control>
</FormField>
</div>
)}
</div>
</div>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? (
<BarLoader
cssOverride={{ borderRadius: 60 }}
width={60}
color="#ffffff"
/>
) : (
'Create Activity'
)}
</ButtonBlack>
</Form.Submit>
</Flex>
</FormLayout>
)
}
export default VideoModal