1- import { useQuery } from "@tanstack/react-query" ;
1+ import { useQuery , useQueryClient } from "@tanstack/react-query" ;
2+ import { getPreset } from "../../api/presetApi" ;
3+ import { fetchLanguageVersions } from "@/components/api/searchApi" ;
24import { Pecha } from "@/components/ui/shadimport" ;
5+ import { useState } from "react" ;
6+ import { VersionSelectorModal } from "@/components/ui/molecules/version-selector/VersionSelectorModal" ;
37import axiosInstance from "@/config/axios-config" ;
48import {
59 ContentIcon ,
@@ -56,6 +60,52 @@ const SubtaskContent = ({
5660 }
5761} ;
5862
63+ const SourceReferenceWithVersion = ( { subtask } : { subtask : any } ) => {
64+ const { data : preset } = useQuery ( {
65+ queryKey : [ "preset" , subtask . id ] ,
66+ queryFn : ( ) => getPreset ( subtask . id ) ,
67+ enabled : ! ! subtask . id ,
68+ } ) ;
69+
70+ const { data : versionsData } = useQuery ( {
71+ queryKey : [ "languageVersions" , subtask . source_text_id , preset ?. language ] ,
72+ queryFn : ( ) =>
73+ fetchLanguageVersions ( subtask . source_text_id , preset ! . language ) ,
74+ enabled : ! ! preset && ! ! subtask . source_text_id && ! ! preset . language ,
75+ } ) ;
76+
77+ const versionTitle = versionsData ?. available_versions ?. find (
78+ ( v : any ) => v . id === preset ?. version_id ,
79+ ) ?. title ;
80+
81+ return (
82+ < div className = "relative" >
83+ < SourceReferenceContent content = { subtask . content } />
84+ { preset && (
85+ < div className = "relative mt-2 ml-4" >
86+ { /* Connecting line */ }
87+ < div className = "absolute -top-2 left-0 w-px h-2 bg-blue-400 dark:bg-blue-500" />
88+ < div className = "absolute top-0 left-0 w-3 h-px bg-blue-400 dark:bg-blue-500" />
89+
90+ { /* Version info box */ }
91+ < div className = "ml-4 flex items-center gap-2 px-3 py-2 bg-blue-50 dark:bg-blue-900/20 rounded-md border border-blue-200 dark:border-blue-800" >
92+ < span className = "text-xs font-semibold text-blue-600 dark:text-blue-400 uppercase tracking-wide" >
93+ { preset . language }
94+ </ span >
95+ < span className = "text-xs text-gray-500 dark:text-gray-400" > •</ span >
96+ < span
97+ className = "text-sm text-gray-700 dark:text-gray-300 truncate max-w-[300px]"
98+ title = { versionTitle || preset . version_id }
99+ >
100+ { versionTitle || preset . version_id . substring ( 0 , 8 ) + "..." }
101+ </ span >
102+ </ div >
103+ </ div >
104+ ) }
105+ </ div >
106+ ) ;
107+ } ;
108+
59109const SubtaskCard = ( {
60110 subtask,
61111 listeners,
@@ -67,47 +117,96 @@ const SubtaskCard = ({
67117 isEditable ?: boolean ;
68118 dayAudioUrl ?: string | null ;
69119} ) => {
120+ const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
121+ const queryClient = useQueryClient ( ) ;
122+
123+ const { data : preset } = useQuery ( {
124+ queryKey : [ "preset" , subtask . id ] ,
125+ queryFn : ( ) => getPreset ( subtask . id ) ,
126+ enabled : ! ! subtask . id && subtask . content_type === "SOURCE_REFERENCE" ,
127+ } ) ;
128+
70129 return (
71- < div
72- className = { `border rounded-xl bg-[#ffffff] dark:bg-[#161616] border-gray-300 dark:border-input p-2 space-y-2` }
73- >
74- < div className = "flex items-center justify-between" >
75- < div className = "flex items-center border w-fit bg-[#F7F7F7] dark:bg-sidebar-secondary px-2 py-1 text-sm rounded-md border-dashed gap-2" >
76- < ContentIcon type = { subtask . content_type } /> { subtask . content_type }
130+ < >
131+ < div
132+ className = { `border rounded-xl bg-[#ffffff] dark:bg-[#161616] border-gray-300 dark:border-input p-2 space-y-2` }
133+ >
134+ < div className = "flex items-center justify-between" >
135+ < div className = "flex items-center gap-2" >
136+ < div className = "flex items-center border w-fit bg-[#F7F7F7] dark:bg-sidebar-secondary px-2 py-1 text-sm rounded-md border-dashed gap-2" >
137+ < ContentIcon type = { subtask . content_type } /> { subtask . content_type }
138+ </ div >
139+ { subtask . content_type === "SOURCE_REFERENCE" &&
140+ ! preset &&
141+ subtask . source_text_id && (
142+ < Pecha . Button
143+ variant = "outline"
144+ size = "sm"
145+ onClick = { ( ) => setIsModalOpen ( true ) }
146+ className = "text-xs"
147+ >
148+ Add Version
149+ </ Pecha . Button >
150+ ) }
151+ </ div >
152+ { listeners && isEditable && (
153+ < PiDotsSixVertical
154+ className = "w-5 h-5 text-gray-400 dark:text-muted-foreground cursor-grab active:cursor-grabbing"
155+ { ...listeners }
156+ />
157+ ) }
77158 </ div >
78- { listeners && isEditable && (
79- < PiDotsSixVertical
80- className = "w-5 h-5 text-gray-400 dark:text-muted-foreground cursor-grab active:cursor-grabbing"
81- { ...listeners }
159+ { subtask . content_type === "SOURCE_REFERENCE" ? (
160+ < SourceReferenceWithVersion subtask = { subtask } />
161+ ) : (
162+ < SubtaskContent
163+ type = { subtask . content_type }
164+ content = { subtask . content }
82165 />
83166 ) }
167+ { subtask . audio_url ? (
168+ < div className = "border-t border-dashed pt-2" >
169+ < audio
170+ controls
171+ src = { subtask . audio_url }
172+ className = "w-full"
173+ preload = "metadata"
174+ />
175+ </ div >
176+ ) : (
177+ subtask . start_ms != null &&
178+ subtask . end_ms != null &&
179+ ( dayAudioUrl ? (
180+ < AudioSegmentPlayer
181+ audioUrl = { dayAudioUrl }
182+ startMs = { subtask . start_ms }
183+ endMs = { subtask . end_ms }
184+ />
185+ ) : (
186+ < p className = "text-xs text-muted-foreground border-t border-dashed pt-2" >
187+ Timeline: { formatMs ( subtask . start_ms ) } –{ " " }
188+ { formatMs ( subtask . end_ms ) }
189+ </ p >
190+ ) )
191+ ) }
84192 </ div >
85- < SubtaskContent type = { subtask . content_type } content = { subtask . content } />
86- { subtask . audio_url ? (
87- < div className = "border-t border-dashed pt-2" >
88- < audio
89- controls
90- src = { subtask . audio_url }
91- className = "w-full"
92- preload = "metadata"
93- />
94- </ div >
95- ) : (
96- subtask . start_ms != null &&
97- subtask . end_ms != null &&
98- ( dayAudioUrl ? (
99- < AudioSegmentPlayer
100- audioUrl = { dayAudioUrl }
101- startMs = { subtask . start_ms }
102- endMs = { subtask . end_ms }
193+
194+ { subtask . content_type === "SOURCE_REFERENCE" &&
195+ subtask . source_text_id && (
196+ < VersionSelectorModal
197+ isOpen = { isModalOpen }
198+ onOpenChange = { setIsModalOpen }
199+ textId = { subtask . source_text_id }
200+ subtaskId = { subtask . id }
201+ onSuccess = { ( ) => {
202+ setIsModalOpen ( false ) ;
203+ queryClient . invalidateQueries ( {
204+ queryKey : [ "preset" , subtask . id ] ,
205+ } ) ;
206+ } }
103207 />
104- ) : (
105- < p className = "text-xs text-muted-foreground border-t border-dashed pt-2" >
106- Timeline: { formatMs ( subtask . start_ms ) } – { formatMs ( subtask . end_ms ) }
107- </ p >
108- ) )
109- ) }
110- </ div >
208+ ) }
209+ </ >
111210 ) ;
112211} ;
113212
0 commit comments