@@ -34,7 +34,7 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
3434 let hackathon = use_context :: < Signal < HackathonInfo > > ( ) ;
3535 let mut status: Signal < Option < JudgingStatus > > = use_signal ( || None ) ;
3636 let mut features: Signal < Vec < FeatureInfo > > = use_signal ( || Vec :: new ( ) ) ;
37- let mut available_users : Signal < Vec < ( i32 , String ) > > = use_signal ( || Vec :: new ( ) ) ;
37+
3838 let mut loading = use_signal ( || false ) ;
3939 let mut error_msg: Signal < Option < String > > = use_signal ( || None ) ;
4040 let mut success_msg: Signal < Option < String > > = use_signal ( || None ) ;
@@ -69,19 +69,6 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
6969 Err ( e) => error_msg. set ( Some ( format ! ( "Failed to get features: {}" , e) ) ) ,
7070 }
7171
72- // Fetch available users for judge assignment
73- match get_hackathon_people ( slug. clone ( ) , None , None , None , None ) . await {
74- Ok ( response) => {
75- let user_list: Vec < ( i32 , String ) > = response
76- . people
77- . into_iter ( )
78- . map ( |u : HackathonPerson | ( u. user_id , u. name . unwrap_or_else ( || u. email ) ) )
79- . collect ( ) ;
80- available_users. set ( user_list) ;
81- }
82- Err ( _) => { } // Silently fail - users just won't be able to add judges
83- }
84-
8572 // Fetch prizes with judges
8673 match get_prizes_with_judges ( slug) . await {
8774 Ok ( p) => prizes_with_judges. set ( p) ,
@@ -270,6 +257,30 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
270257 }
271258 } ;
272259
260+ // Resource for searching judges
261+ let mut judges_resource = use_resource ( use_reactive (
262+ & ( slug. clone ( ) , prize_judge_search ( ) ) ,
263+ move |( slug, search) | async move {
264+ let search_val = if search. trim ( ) . is_empty ( ) {
265+ None
266+ } else {
267+ Some ( search)
268+ } ;
269+ get_hackathon_people (
270+ slug,
271+ Some ( 0 ) ,
272+ Some ( 20 ) ,
273+ search_val,
274+ Some ( vec ! [
275+ "judge" . to_string( ) ,
276+ "organizer" . to_string( ) ,
277+ "admin" . to_string( ) ,
278+ ] ) ,
279+ )
280+ . await
281+ } ,
282+ ) ) ;
283+
273284 let mut select_feature = move |feature : FeatureInfo | {
274285 edit_name. set ( feature. name . clone ( ) ) ;
275286 edit_description. set ( feature. description . clone ( ) . unwrap_or_default ( ) ) ;
@@ -648,6 +659,7 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
648659
649660
650661
662+
651663 if let Some ( desc) = & feature. description {
652664 p { class: "text-sm text-foreground-neutral-secondary line-clamp-3" , "{desc}" }
653665 }
@@ -779,33 +791,6 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
779791 show_prize_judge_picker. set( false ) ;
780792 prize_judge_search. set( String :: new( ) ) ;
781793 } ,
782-
783-
784-
785-
786-
787-
788-
789-
790-
791-
792-
793-
794-
795-
796-
797-
798-
799-
800-
801-
802-
803-
804-
805-
806-
807-
808-
809794 div { class: "flex items-center justify-between mb-2" ,
810795 h3 { class: "font-semibold text-lg text-foreground-neutral-primary" , "{pwj.prize.name}" }
811796 if pwj. is_default {
@@ -819,6 +804,7 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
819804 }
820805 }
821806
807+
822808 if !pwj. is_default && !pwj. judges. is_empty( ) {
823809 div { class: "flex flex-wrap gap-2 mt-2" ,
824810 for judge in pwj. judges. iter( ) . take( 5 ) {
@@ -861,116 +847,12 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
861847 selected_prize. set( None ) ;
862848 show_prize_judge_picker. set( false ) ;
863849 } ,
864-
865- // Assigned judges list
866-
867- // Update selected judges
868-
869- // Judge picker dropdown
870- // Update selected judges
871-
872- // Make Default button
873-
874-
875-
876-
877-
878-
879-
880-
881-
882-
883-
884-
885-
886-
887-
888-
889-
890-
891-
892-
893-
894-
895-
896-
897-
898-
899-
900-
901-
902-
903-
904-
905-
906-
907-
908-
909-
910-
911-
912-
913-
914-
915-
916-
917-
918-
919-
920-
921-
922-
923-
924-
925-
926-
927-
928-
929-
930-
931-
932-
933-
934-
935-
936-
937-
938-
939-
940-
941-
942-
943-
944-
945-
946-
947-
948-
949-
950-
951-
952-
953-
954-
955-
956-
957-
958-
959-
960-
961-
962-
963-
964-
965-
966-
967-
968-
969-
970850 Icon { width: 20 , height: 20 , icon: LdX }
971851 }
972852 }
973853
854+
855+
974856 div { class: "mb-4" ,
975857 div { class: "flex items-center justify-between mb-2" ,
976858 label { class: "text-sm text-foreground-neutral-secondary" , "Assigned Judges" }
@@ -1041,54 +923,66 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
1041923 }
1042924 div { class: "max-h-48 overflow-y-auto space-y-1" ,
1043925 {
1044- let search = prize_judge_search. read( ) . to_lowercase( ) ;
926+ let judges_result = judges_resource. read( ) ;
927+ let filtered_judges = match judges_result. as_ref( ) {
928+ Some ( Ok ( response) ) => response. people. clone( ) ,
929+ _ => Vec :: new( ) ,
930+ } ;
931+
1045932 let assigned_ids: Vec <i32 > = selected_prize_judges
1046933 . read( )
1047934 . iter( )
1048935 . map( |j| j. user_id)
1049936 . collect( ) ;
1050- let filtered: Vec <_> = available_users
1051- . read( )
1052- . iter( )
1053- . filter( |( id, name) | {
1054- !assigned_ids. contains( id) && name. to_lowercase( ) . contains( & search)
1055- } )
1056- . take( 10 )
1057- . cloned( )
1058- . collect( ) ;
937+
1059938 rsx! {
1060- for ( id , name) in filtered {
1061- {
1062- let slug = slug. clone( ) ;
1063- let refresh = refresh. clone( ) ;
1064- let prize_id = selected_prize. read( ) . as_ref( ) . map( |p| p. id) . unwrap_or_default( ) ;
1065- rsx! {
1066- button {
1067- class: "w-full text-left px-3 py-2 hover:bg-background-neutral-secondary-enabled rounded cursor-pointer" ,
1068- onclick: move |_| {
1069- let slug = slug. clone( ) ;
1070- let refresh = refresh. clone( ) ;
1071- spawn( async move {
1072- let request = AssignJudgesRequest {
1073- judge_ids: vec![ id] ,
1074- } ;
1075- if assign_prize_judges( slug. clone( ) , prize_id, request) . await . is_ok( ) {
1076- refresh( ) ;
1077- if let Ok ( p) = get_prizes_with_judges( slug) . await {
1078- prizes_with_judges. set( p. clone( ) ) ;
1079- let judges = p
1080- . iter( )
1081- . find( |pwj| pwj. prize. id == prize_id)
1082- . map( |pwj| pwj. judges. clone( ) )
1083- . unwrap_or_default( ) ;
1084- selected_prize_judges. set( judges) ;
1085- }
1086- show_prize_judge_picker. set( false ) ;
1087- prize_judge_search. set( String :: new( ) ) ;
1088- }
1089- } ) ;
1090- } ,
1091- "{name}"
939+ if let Some ( Err ( e) ) = judges_result. as_ref( ) {
940+ div { class: "p-2 text-sm text-foreground-danger-primary" ,
941+ "Error loading judges: {e}"
942+ }
943+ } else if filtered_judges. is_empty( ) {
944+ div { class: "p-2 text-sm text-foreground-neutral-secondary" ,
945+ "No judges found."
946+ }
947+ } else {
948+ for person in filtered_judges {
949+ if !assigned_ids. contains( & person. user_id) {
950+ {
951+ let id = person. user_id;
952+ let name = person. name. clone( ) . unwrap_or_else( || person. email. clone( ) ) ;
953+ let slug = slug. clone( ) ;
954+ let refresh = refresh. clone( ) ;
955+ let prize_id = selected_prize. read( ) . as_ref( ) . map( |p| p. id) . unwrap_or_default( ) ;
956+
957+ rsx! {
958+ button {
959+ class: "w-full text-left px-3 py-2 hover:bg-background-neutral-secondary-enabled rounded cursor-pointer" ,
960+ onclick: move |_| {
961+ let slug = slug. clone( ) ;
962+ let refresh = refresh. clone( ) ;
963+ spawn( async move {
964+ let request = AssignJudgesRequest {
965+ judge_ids: vec![ id] ,
966+ } ;
967+ if assign_prize_judges( slug. clone( ) , prize_id, request) . await . is_ok( ) {
968+ refresh( ) ;
969+ if let Ok ( p) = get_prizes_with_judges( slug) . await {
970+ prizes_with_judges. set( p. clone( ) ) ;
971+ let judges = p
972+ . iter( )
973+ . find( |pwj| pwj. prize. id == prize_id)
974+ . map( |pwj| pwj. judges. clone( ) )
975+ . unwrap_or_default( ) ;
976+ selected_prize_judges. set( judges) ;
977+ }
978+ show_prize_judge_picker. set( false ) ;
979+ prize_judge_search. set( String :: new( ) ) ;
980+ }
981+ } ) ;
982+ } ,
983+ "{name}"
984+ }
985+ }
1092986 }
1093987 }
1094988 }
@@ -1126,9 +1020,9 @@ pub fn HackathonJudgingAdmin(slug: String) -> Element {
11261020 } ,
11271021 "Assign All Judges"
11281022 }
1129-
11301023 }
11311024 }
1025+
11321026 }
11331027 }
11341028 }
0 commit comments