| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 
 | use yew::prelude::*;
 #[derive(Clone, PartialEq)]
 struct Video {
 id: usize,
 title: String,
 speaker: String,
 url: String,
 }
 
 #[derive(Properties, PartialEq)]
 struct VideosListProps {
 videos: Vec<Video>,
 on_click: Callback<Video>,
 }
 
 #[derive(Clone, Properties, PartialEq)]
 struct VideosDetailsProps {
 video: Video,
 }
 
 #[function_component(VideoDetails)]
 fn video_details(VideosDetailsProps { video }: &VideosDetailsProps) -> Html {
 html! {
 <div>
 <h3>{ video.title.clone() }</h3>
 <img src="https://via.placeholder.com/640x360.png?text=Video+Player+Placeholder" alt="video thumbnail" />
 </div>
 }
 }
 
 #[function_component(VideosList)]
 fn videos_list(VideosListProps { videos, on_click }: &VideosListProps) -> Html {
 videos
 .iter()
 .map(|video| {
 let on_video_select = {
 let on_click = on_click.clone();
 let video = video.clone();
 Callback::from(move |_| on_click.emit(video.clone()))
 };
 html! {
 <p onclick={on_video_select} style="cursor: pointer;">{format!("{}: {}", video.speaker, video.title)}</p>
 }
 })
 .collect()
 }
 
 #[function_component(App)]
 pub fn app() -> Html {
 let videos = vec![
 Video {
 id: 1,
 title: "Building and breaking things".to_string(),
 speaker: "John Doe".to_string(),
 url: "https://youtu.be/PsaFVLr8t4E".to_string(),
 },
 Video {
 id: 2,
 title: "The development process".to_string(),
 speaker: "Jane Smith".to_string(),
 url: "https://youtu.be/PsaFVLr8t4E".to_string(),
 },
 Video {
 id: 3,
 title: "The Web 7.0".to_string(),
 speaker: "Matt Miller".to_string(),
 url: "https://youtu.be/PsaFVLr8t4E".to_string(),
 },
 Video {
 id: 4,
 title: "Mouseless development".to_string(),
 speaker: "Tom Jerry".to_string(),
 url: "https://youtu.be/PsaFVLr8t4E".to_string(),
 },
 ];
 
 let selected_video = use_state(|| None);
 
 let on_video_select = {
 let selected_video = selected_video.clone();
 Callback::from(move |video: Video| selected_video.set(Some(video)))
 };
 
 let details = selected_video.as_ref().map(|video| {
 html! {
 <VideoDetails video={video.clone()} />
 }
 });
 
 html! {
 <>
 <h1>{ "RustConf Explorer" }</h1>
 <div>
 <h3>{ "Videos to watch" }</h3>
 <VideosList videos={videos} on_click={on_video_select} />
 </div>
 { for details }
 </>
 }
 }
 
 |