@@ -11,6 +11,7 @@ use crate::{
1111} ;
1212use anyhow:: Context ;
1313use chrono:: { Datelike , Local } ;
14+ use log:: info;
1415use std:: collections:: HashSet ;
1516use std:: rc:: Rc ;
1617use tokio:: sync:: Mutex ;
@@ -42,14 +43,14 @@ impl<'a> CommandClient<'a> {
4243 }
4344 }
4445
45- pub ( crate ) async fn get_table ( & self , week : Option < & WeekNumber > ) -> anyhow:: Result < ( ) > {
46+ pub ( crate ) async fn get_table ( & self , week : & WeekNumber ) -> anyhow:: Result < ( ) > {
4647 let time_sheet = self . repository . lock ( ) . await . get_time_sheet ( week) . await ?;
4748
4849 println ! ( "{time_sheet}" ) ;
4950 Ok ( ( ) )
5051 }
5152
52- async fn get_json ( & self , week : Option < & WeekNumber > ) -> anyhow:: Result < ( ) > {
53+ async fn get_json ( & self , week : & WeekNumber ) -> anyhow:: Result < ( ) > {
5354 let time_sheet = self . repository . lock ( ) . await . get_time_sheet ( week) . await ?;
5455 let json =
5556 serde_json:: to_string ( & time_sheet) . context ( "Failed to deserialize time sheet" ) ?;
@@ -58,12 +59,13 @@ impl<'a> CommandClient<'a> {
5859 Ok ( ( ) )
5960 }
6061
61- pub ( crate ) async fn get ( & self , week : Option < u8 > , year : Option < i32 > , format : Format ) {
62- let week = to_week_with_fallback ( week, year) ;
62+ pub ( crate ) async fn get ( & self , week : Option < String > , year : Option < i32 > , format : Format ) {
63+ let week =
64+ get_week_with_fallback ( week, year) . unwrap_or_else ( |err| exit_with_error ! ( "{err}" ) ) ;
6365
6466 match format {
65- Format :: Json => self . get_json ( week. as_ref ( ) ) . await . context ( "JSON" ) ,
66- Format :: Table => self . get_table ( week. as_ref ( ) ) . await . context ( "table" ) ,
67+ Format :: Json => self . get_json ( & week) . await . context ( "JSON" ) ,
68+ Format :: Table => self . get_table ( & week) . await . context ( "table" ) ,
6769 }
6870 . unwrap_or_else ( |err| {
6971 exit_with_error ! ( "Failed to get time sheet as {}" , error_stack_fmt( & err) ) ;
@@ -74,7 +76,7 @@ impl<'a> CommandClient<'a> {
7476 & mut self ,
7577 hours : f32 ,
7678 days : Option < Days > ,
77- week : Option < u8 > ,
79+ week : Option < String > ,
7880 year : Option < i32 > ,
7981 job : & str ,
8082 task : & str ,
@@ -84,12 +86,13 @@ impl<'a> CommandClient<'a> {
8486 }
8587
8688 let day = get_days ( days) ;
87- let week = to_week_with_fallback ( week, year) ;
89+ let week =
90+ get_week_with_fallback ( week, year) . unwrap_or_else ( |err| exit_with_error ! ( "{err}" ) ) ;
8891
8992 self . time_sheet_service
9093 . lock ( )
9194 . await
92- . set_time ( hours, & day, week. as_ref ( ) , job, task)
95+ . set_time ( hours, & day, & week, job, task)
9396 . await
9497 . unwrap_or_else ( |err| {
9598 if let SetTimeError :: Unknown ( err) = err {
@@ -105,18 +108,19 @@ impl<'a> CommandClient<'a> {
105108 job : & str ,
106109 task : & str ,
107110 days : Option < Days > ,
108- week : Option < u8 > ,
111+ week : Option < String > ,
109112 year : Option < i32 > ,
110113 ) {
111114 if days. as_ref ( ) . is_some_and ( |days| days. is_empty ( ) ) {
112115 exit_with_error ! ( "`--day` is set but no day was provided" ) ;
113116 }
114117
115- let week = to_week_with_fallback ( week, year) ;
118+ let week =
119+ get_week_with_fallback ( week, year) . unwrap_or_else ( |err| exit_with_error ! ( "{err}" ) ) ;
116120 self . time_sheet_service
117121 . lock ( )
118122 . await
119- . clear ( job, task, & get_days ( days) , week. as_ref ( ) )
123+ . clear ( job, task, & get_days ( days) , & week)
120124 . await
121125 . unwrap_or_else ( |err| {
122126 if let SetTimeError :: Unknown ( err) = err {
@@ -136,28 +140,31 @@ impl<'a> CommandClient<'a> {
136140 pub ( crate ) async fn delete (
137141 & mut self ,
138142 line_number : & LineNumber ,
139- week : Option < u8 > ,
143+ week : Option < String > ,
140144 year : Option < i32 > ,
141145 ) {
142- let week = to_week_with_fallback ( week, year) ;
146+ let week =
147+ get_week_with_fallback ( week, year) . unwrap_or_else ( |err| exit_with_error ! ( "{err}" ) ) ;
143148
144149 self . repository
145150 . lock ( )
146151 . await
147- . delete_line ( line_number, week. as_ref ( ) )
152+ . delete_line ( line_number, & week)
148153 . await
149154 . unwrap_or_else ( |err| {
150155 let source = error_stack_fmt ( & err) ;
151156 exit_with_error ! ( "Failed to delete line {line_number:?}: {source}" ) ;
152157 } ) ;
153158 }
154159
155- pub ( crate ) async fn submit ( & mut self , week : Option < u8 > , year : Option < i32 > ) {
156- let week = to_week_with_fallback ( week, year) ;
160+ pub ( crate ) async fn submit ( & mut self , week : Option < String > , year : Option < i32 > ) {
161+ let week =
162+ get_week_with_fallback ( week, year) . unwrap_or_else ( |err| exit_with_error ! ( "{err}" ) ) ;
163+
157164 self . repository
158165 . lock ( )
159166 . await
160- . submit ( week. as_ref ( ) )
167+ . submit ( & week)
161168 . await
162169 . unwrap_or_else ( |err| {
163170 exit_with_error ! ( "Failed to submit: {}" , error_stack_fmt( & err) ) ;
@@ -173,8 +180,35 @@ fn get_days(days: Option<Days>) -> Days {
173180 } )
174181}
175182
176- fn to_week_with_fallback ( week : Option < u8 > , year : Option < i32 > ) -> Option < WeekNumber > {
177- week. map ( |week| {
178- WeekNumber :: new_with_fallback ( week, year) . unwrap_or_else ( |err| exit_with_error ! ( "{err}" ) )
179- } )
183+ // TODO: refactor this so that it lives on WeekNumber and parse_week calls this instead of
184+ // vice-versa
185+ fn get_week_with_fallback ( week : Option < String > , year : Option < i32 > ) -> anyhow:: Result < WeekNumber > {
186+ if let Some ( week) = week {
187+ let week = parse_week ( week) ?;
188+
189+ let week = WeekNumber :: new_with_fallback ( week, year) ?;
190+ Ok ( week)
191+ } else {
192+ let week = Local :: now ( ) . date_naive ( ) . iso_week ( ) . week ( ) . try_into ( ) ;
193+ let week = week. expect ( "Week numbers are always less than 255" ) ;
194+
195+ WeekNumber :: new_with_fallback ( week, year)
196+ }
197+ }
198+
199+ fn parse_week ( week : String ) -> anyhow:: Result < u8 > {
200+ let week = match week. trim ( ) . to_lowercase ( ) . as_str ( ) {
201+ "previous" => {
202+ let week = Local :: now ( ) . date_naive ( ) . iso_week ( ) . week ( ) - 1 ;
203+ info ! ( "Using previous week number: {week}" ) ;
204+ Ok ( week)
205+ }
206+ number => number
207+ . parse ( )
208+ . with_context ( || format ! ( "Invalid week number '{week}'" ) ) ,
209+ } ?
210+ . try_into ( )
211+ . expect ( "Week numbers are always less than 255" ) ;
212+
213+ Ok ( week)
180214}
0 commit comments