@@ -10,6 +10,7 @@ import States from '#enums/states'
1010import VideoTypes , { VideoTypeDesc , VideoTypesOrdered } from ' #enums/video_types'
1111import { useForm } from ' @inertiajs/vue3'
1212import { Link } from ' @tuyau/inertia/vue'
13+ import axios from ' axios'
1314import {
1415 BookCheck ,
1516 BookDashed ,
@@ -18,9 +19,11 @@ import {
1819 ChevronsUpDown ,
1920 Plus ,
2021 Trash2 ,
22+ LucideLoader ,
2123} from ' lucide-vue-next'
2224import { DateTime } from ' luxon'
23- import { computed } from ' vue'
25+ import { computed , ref } from ' vue'
26+ import { toast } from ' vue-sonner'
2427import { tuyau } from ' ~/lib/tuyau'
2528import { enumKeys } from ' ~/lib/utils'
2629
@@ -29,6 +32,24 @@ const props = defineProps<{
2932 taxonomies: TaxonomyDto []
3033}>()
3134
35+ const r2DefaultCaptions = [
36+ {
37+ type: CaptionTypes .SRT ,
38+ language: CaptionLanguages .ENGLISH ,
39+ label: ' ' ,
40+ },
41+ {
42+ type: CaptionTypes .SRT ,
43+ language: CaptionLanguages .SPANISH ,
44+ label: ' ' ,
45+ },
46+ {
47+ type: CaptionTypes .SRT ,
48+ language: CaptionLanguages .FRENCH ,
49+ label: ' ' ,
50+ },
51+ ]
52+
3253const form = useForm ({
3354 title: props .post ?.title ?? ' ' ,
3455 slug: props .post ?.slug ?? ' ' ,
@@ -63,6 +84,8 @@ const form = useForm({
6384 taxonomyIds: props .post ?.taxonomyIds ?? [],
6485})
6586
87+ const isGeneratingChapters = ref (false )
88+
6689const publishAt = computed (() => {
6790 const iso = [form .publishAtDate , form .publishAtTime ].filter (Boolean ).join (' T' )
6891 return iso && DateTime .fromISO (iso )
@@ -81,6 +104,29 @@ function secondsToTimecode(seconds: number) {
81104 .join (' :' )
82105}
83106
107+ async function generateVideoChapters() {
108+ if (form .chapters .length || ! form .videoUrl ) return
109+
110+ isGeneratingChapters .value = true
111+
112+ try {
113+ const { data } = await axios .post (` /ai/videos/${form .videoUrl }/chapters ` )
114+
115+ if (Array .isArray (data .result .response )) {
116+ form .chapters = data .result .response
117+
118+ toast .success (' Chapters generated successfully' )
119+ } else {
120+ toast .error (' Chapters were generated successfully, but came back in an unexpected format' )
121+ }
122+ } catch (error ) {
123+ console .error (error )
124+ toast .error (' Failed to generate chapters' )
125+ }
126+
127+ isGeneratingChapters .value = false
128+ }
129+
84130function onSubmit(stateId : States = Number (form .stateId )) {
85131 const action = form .transform ((data ) => {
86132 data .stateId = stateId
@@ -93,6 +139,13 @@ function onSubmit(stateId: States = Number(form.stateId)) {
93139
94140 action .post (tuyau .$url (' posts.store' ))
95141}
142+
143+ function onVideoTypeChanged(videoTypeId : string ) {
144+ if (form .chapters .length ) return
145+ if (videoTypeId !== VideoTypes .R2 .toString ()) return
146+
147+ form .captions = r2DefaultCaptions .map ((r ) => ({ ... r }))
148+ }
96149 </script >
97150
98151<template >
@@ -317,6 +370,7 @@ function onSubmit(stateId: States = Number(form.stateId)) {
317370 v-model =" form .videoTypeId "
318371 placeholder="Have a video? Where is it stored?"
319372 :errors =" form .errors .videoTypeId "
373+ @update :modelValue =" onVideoTypeChanged "
320374 >
321375 <SelectItem v-for =" id in VideoTypesOrdered " :key =" id " :value =" id .toString ()" >
322376 {{ VideoTypeDesc[id] }}
@@ -348,6 +402,7 @@ function onSubmit(stateId: States = Number(form.stateId)) {
348402 v-model =" form .videoUrl "
349403 :max =" 255 "
350404 placeholder="Enter the R2 Video Id (directory name)"
405+ @blur =" generateVideoChapters "
351406 />
352407
353408 <FormInput
@@ -427,7 +482,15 @@ function onSubmit(stateId: States = Number(form.stateId)) {
427482 v-if =" Number(form.videoTypeId) === VideoTypes.R2"
428483 class =" -mx-4 p-4 border border-slate-300 rounded-lg"
429484 >
430- <legend class =" -mx-2 px-2" >Chapters</legend >
485+ <legend class =" -mx-2 px-2" >
486+ Chapters
487+ <span
488+ v-show =" isGeneratingChapters"
489+ class =" text-slate-400 inline-flex items-center gap-1.5"
490+ >
491+ [Generating <LucideLoader class="w-4 h-4 animate-spin" />]
492+ </span >
493+ </legend >
431494
432495 <div
433496 v-if =" form.chapters"
0 commit comments