@@ -39,15 +39,24 @@ pub fn replay_from(entries: impl IntoIterator<Item = WalEntry>) -> Board {
3939 }
4040 WalEvent :: Move { id, to } => {
4141 if let Some ( task) = tasks. get_mut ( & id) {
42- if to == Column :: Doing && task. started_at . is_none ( ) {
43- task. started_at = Some ( entry. ts ) ;
42+ match to {
43+ Column :: Todo => {
44+ task. started_at = None ;
45+ task. done_at = None ;
46+ task. column = Column :: Todo ;
47+ }
48+ Column :: Doing => {
49+ if task. started_at . is_none ( ) {
50+ task. started_at = Some ( entry. ts ) ;
51+ }
52+ task. done_at = None ;
53+ task. column = Column :: Doing ;
54+ }
55+ Column :: Done => {
56+ task. done_at = Some ( entry. ts ) ;
57+ task. column = Column :: Done ;
58+ }
4459 }
45- if to == Column :: Done {
46- task. done_at = Some ( entry. ts ) ;
47- } else {
48- task. done_at = None ;
49- }
50- task. column = to;
5160 }
5261 }
5362 WalEvent :: Edit { id, title } => {
@@ -135,6 +144,41 @@ mod tests {
135144 assert_eq ! ( board. done[ 0 ] . id, id) ;
136145 }
137146
147+ #[ test]
148+ fn replay_move_to_todo_clears_started_at ( ) {
149+ let id = "01TESTTESTTESTTESTTEST" . to_string ( ) ;
150+ let entries = vec ! [
151+ WalEntry {
152+ ts: Utc . with_ymd_and_hms( 2026 , 4 , 1 , 10 , 0 , 0 ) . unwrap( ) ,
153+ event: WalEvent :: Add {
154+ id: id. clone( ) ,
155+ title: "t" . to_string( ) ,
156+ tags: vec![ ] ,
157+ day: "2026-04-01" . to_string( ) ,
158+ } ,
159+ } ,
160+ WalEntry {
161+ ts: Utc . with_ymd_and_hms( 2026 , 4 , 2 , 10 , 0 , 0 ) . unwrap( ) ,
162+ event: WalEvent :: Move {
163+ id: id. clone( ) ,
164+ to: Column :: Doing ,
165+ } ,
166+ } ,
167+ WalEntry {
168+ ts: Utc . with_ymd_and_hms( 2026 , 4 , 3 , 10 , 0 , 0 ) . unwrap( ) ,
169+ event: WalEvent :: Move {
170+ id: id. clone( ) ,
171+ to: Column :: Todo ,
172+ } ,
173+ } ,
174+ ] ;
175+ let board = replay_from ( entries) ;
176+ assert_eq ! ( board. todo. len( ) , 1 ) ;
177+ assert_eq ! ( board. todo[ 0 ] . id, id) ;
178+ assert ! ( board. todo[ 0 ] . started_at. is_none( ) ) ;
179+ assert ! ( board. todo[ 0 ] . done_at. is_none( ) ) ;
180+ }
181+
138182 #[ test]
139183 fn daily_view_filters_done_only ( ) {
140184 use chrono:: Local ;
0 commit comments