1use actix_web::{
4 delete, get, patch, post,
5 web::{Json, Path, Query},
6 HttpResponse, Result,
7};
8use uuid::Uuid;
9
10use crate::{
11 config::{
12 auth::user_info::UserInfo,
13 data::{SharedBroadcaster, SharedPool},
14 },
15 model::dto::{
16 actions::Action,
17 areas::{AreaKind, AreaSearchParameters, AreaUpdate, NewAreaDto, UpdateAreaDto},
18 core::ActionDtoWrapper,
19 },
20 service::areas,
21};
22
23#[utoipa::path(
28 context_path = "/api/maps/{map_id}/areas",
29 params(
30 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
31 AreaSearchParameters
32 ),
33 responses(
34 (status = 200, description = "Find areas", body = Vec<AreaDto>),
35 ),
36 security(
37 ("oauth2" = [])
38 )
39)]
40#[get("")]
41pub async fn find(
42 search_params: Query<AreaSearchParameters>,
43 pool: SharedPool,
44) -> Result<HttpResponse> {
45 let response = areas::find(search_params.into_inner(), &pool).await?;
46 Ok(HttpResponse::Ok().json(response))
47}
48
49#[utoipa::path(
54 context_path = "/api/maps/{map_id}/areas",
55 params(
56 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
57 ("area_kind" = AreaKind, Path, description = "The type of area"),
58 ),
59 request_body = NewAreaDto,
60 responses(
61 (status = 201, description = "Create an areas", body = AreaDto)
62 ),
63 security(
64 ("oauth2" = [])
65 )
66)]
67#[post("/{area_kind}")]
68pub async fn create(
69 path: Path<(i32, AreaKind)>,
70 new_areas: Json<ActionDtoWrapper<Vec<NewAreaDto>>>,
71 pool: SharedPool,
72 broadcaster: SharedBroadcaster,
73 user_info: UserInfo,
74) -> Result<HttpResponse> {
75 let (map_id, area_kind) = path.into_inner();
76
77 let ActionDtoWrapper { action_id, dto } = new_areas.into_inner();
78
79 let created_areas = areas::create(area_kind, dto, &pool).await?;
80
81 broadcaster
82 .broadcast(
83 map_id,
84 Action::new_create_area_action(
85 area_kind,
86 created_areas.clone(),
87 user_info.id,
88 action_id,
89 ),
90 )
91 .await;
92
93 Ok(HttpResponse::Created().json(created_areas))
94}
95
96#[utoipa::path(
101 context_path = "/api/maps/{map_id}/areas",
102 params(
103 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
104 ("area_kind" = AreaKind, Path, description = "The type of area"),
105 ),
106 request_body = ActionDtoWrapperUpdateAreas,
107 responses(
108 (status = 200, description = "Update multiple areas of the same kind", body = Vec<AreaDto>)
109 ),
110 security(
111 ("oauth2" = [])
112 )
113)]
114#[patch("/{area_kind}")]
115pub async fn update(
116 path: Path<(i32, AreaKind)>,
117 update_areas: Json<ActionDtoWrapper<UpdateAreaDto>>,
118 pool: SharedPool,
119 broadcaster: SharedBroadcaster,
120 user_info: UserInfo,
121) -> Result<HttpResponse> {
122 let (map_id, area_kind) = path.into_inner();
123
124 let ActionDtoWrapper { action_id, dto } = update_areas.into_inner();
125
126 let updated = areas::update(area_kind, dto.clone(), &pool).await?;
127
128 let user_id = user_info.id;
129 let action = match dto.update {
130 AreaUpdate::UpdateValue(_) => {
131 Action::new_update_area_action(area_kind, &updated, user_id, action_id)
132 }
133 AreaUpdate::UpdateAddDate(_) => {
134 Action::new_update_area_add_date_action(area_kind, &updated, user_id, action_id)
135 }
136 AreaUpdate::UpdateRemoveDate(_) => {
137 Action::new_update_area_remove_date_action(area_kind, &updated, user_id, action_id)
138 }
139 AreaUpdate::UpdateNotes(_) => {
140 Action::new_update_area_notes_action(area_kind, &updated, user_id, action_id)
141 }
142 };
143 broadcaster.broadcast(map_id, action).await;
144
145 Ok(HttpResponse::Ok().json(updated))
146}
147
148#[utoipa::path(
153 context_path = "/api/maps/{map_id}/areas",
154 params(
155 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
156 ("area_kind" = AreaKind, Path, description = "The type of area"),
157 ),
158 request_body = ActionDtoWrapperDeleteAreas,
159 responses(
160 (status = 200, description = "Areas deleted")
161 ),
162 security(
163 ("oauth2" = [])
164 )
165)]
166#[delete("/{area_kind}")]
167pub async fn delete(
168 path: Path<(i32, AreaKind)>,
169 ids: Json<ActionDtoWrapper<Vec<Uuid>>>,
170 pool: SharedPool,
171 broadcaster: SharedBroadcaster,
172 user_info: UserInfo,
173) -> Result<HttpResponse> {
174 let (map_id, area_kind) = path.into_inner();
175
176 let ActionDtoWrapper { action_id, dto } = ids.into_inner();
177
178 areas::delete_by_ids(area_kind, dto.clone(), &pool).await?;
179
180 broadcaster
181 .broadcast(
182 map_id,
183 Action::new_delete_area_action(area_kind, dto, user_info.id, action_id),
184 )
185 .await;
186
187 Ok(HttpResponse::Ok().finish())
188}