@@ -3,8 +3,10 @@ import { adminClient } from "@/lib/safe-action";
33import { coursesTags , courses , users , tags } from "@/db/schema" ;
44import { courseSchema , type CourseFormValues } from "@/lib/validations/course" ;
55import { db } from "@/db" ;
6- import { eq } from "drizzle-orm" ;
6+ import { eq , inArray } from "drizzle-orm" ;
77import { CourseWithData } from "@/lib/types" ;
8+ import { units , lessons } from "@/db/schema" ;
9+ import { z } from "zod" ;
810
911export const createCourseAction = adminClient
1012 . schema ( courseSchema )
@@ -109,4 +111,90 @@ export async function getCourseById(id: number) {
109111 } ;
110112
111113 return course ;
112- }
114+ }
115+
116+ export const updateLessonUnitOrder = adminClient
117+ . schema (
118+ z . object ( {
119+ updatedUnits : z . array (
120+ z . object ( {
121+ id : z . number ( ) ,
122+ position : z . number ( ) ,
123+ } )
124+ ) ,
125+ updatedLessons : z . array (
126+ z . object ( {
127+ id : z . number ( ) ,
128+ unitId : z . number ( ) ,
129+ position : z . number ( ) ,
130+ } )
131+ ) ,
132+ } )
133+ )
134+ . action ( async ( { parsedInput, ctx } ) => {
135+ const { updatedUnits, updatedLessons } = parsedInput ;
136+
137+ try {
138+ // --- Step 1: Validate unit IDs exist ---
139+ const dbUnits = await db . select ( ) . from ( units ) . where ( inArray ( units . id , updatedUnits . map ( u => u . id ) ) ) ;
140+ if ( dbUnits . length !== updatedUnits . length ) {
141+ return { success : false , message : "One or more units are invalid." } ;
142+ }
143+
144+ // --- Step 2: Validate lesson IDs exist ---
145+ const dbLessons = await db . select ( ) . from ( lessons ) . where ( inArray ( lessons . id , updatedLessons . map ( l => l . id ) ) ) ;
146+ if ( dbLessons . length !== updatedLessons . length ) {
147+ return { success : false , message : "One or more lessons are invalid." } ;
148+ }
149+
150+ // --- Step 3: Check unique and sequential positions for units ---
151+ const unitPositions = updatedUnits . map ( u => u . position ) ;
152+ const uniqueUnitPositions = new Set ( unitPositions ) ;
153+ if ( uniqueUnitPositions . size !== updatedUnits . length ) {
154+ return { success : false , message : "Duplicate positions found for units." } ;
155+ }
156+
157+ const sortedUnitPositions = [ ...unitPositions ] . sort ( ( a , b ) => a - b ) ;
158+ for ( let i = 0 ; i < sortedUnitPositions . length ; i ++ ) {
159+ if ( sortedUnitPositions [ i ] !== i + 1 ) {
160+ return { success : false , message : "Unit positions must be sequential starting from 1." } ;
161+ }
162+ }
163+
164+ // --- Step 4: Check unique and sequential positions for lessons within each unit ---
165+ const lessonsByUnit = updatedLessons . reduce ( ( acc : Record < number , number [ ] > , l ) => {
166+ if ( ! acc [ l . unitId ] ) acc [ l . unitId ] = [ ] ;
167+ acc [ l . unitId ] . push ( l . position ) ;
168+ return acc ;
169+ } , { } as Record < number , number [ ] > ) ;
170+
171+ for ( const unitId in lessonsByUnit ) {
172+ const positions = lessonsByUnit [ unitId ] . sort ( ( a , b ) => a - b ) ;
173+ for ( let i = 0 ; i < positions . length ; i ++ ) {
174+ if ( positions [ i ] !== i + 1 ) {
175+ return { success : false , message : `Lesson positions in unit ${ unitId } must be sequential starting from 1.` } ;
176+ }
177+ }
178+ }
179+
180+ // --- Step 5: Update within a transaction ---
181+ await db . transaction ( async ( tx ) => {
182+ for ( const unit of updatedUnits ) {
183+ await tx . update ( units )
184+ . set ( { position : unit . position } )
185+ . where ( eq ( units . id , unit . id ) ) ;
186+ }
187+
188+ for ( const lesson of updatedLessons ) {
189+ await tx . update ( lessons )
190+ . set ( { position : lesson . position , unitId : lesson . unitId } )
191+ . where ( eq ( lessons . id , lesson . id ) ) ;
192+ }
193+ } ) ;
194+
195+ return { success : true , message : "Units and lessons order updated successfully." } ;
196+ } catch ( error ) {
197+ console . error ( "Failed to update lesson/unit order" , error ) ;
198+ return { success : false , message : "Failed to update order." } ;
199+ }
200+ } ) ;
0 commit comments