Dev.to WebDev 🛠 Dev 👁 0 📖 2 min read

A day planner where one drag re-flows the whole day

Whenever a meeting moved, I ended up dragging five blocks around by hand. Calendar apps let you move one block and leave the overlaps for you to fix. I wanted the other half of the move done for me, and visible before I

A day planner where one drag re-flows the whole day

Whenever a meeting moved, I ended up dragging five blocks around by hand. Calendar apps let you move one block and leave the overlaps for you to fix. I wanted the other half of the move done for me, and visible before I commit to it.

So I built Jostle. You drag one card, and while you still hold it, the cards after it slide around your fixed appointments.

A card is dragged from 8:30 to 10:00, the cards after it slide around the locked appointments, undo puts them back, then a card from the tray is dropped in

The rules

The planner is six rules, and a test checks each one.

  1. The card you hold lands where you drop it. If that spot overlaps a fixed appointment, it lands in the nearest gap it fits.
  2. Fixed items never move, and nothing lands on top of them.
  3. Flexible tasks keep their order and only move later, and only as far as they must.
  4. Gaps stay gaps. Nothing slides up to fill the hole you left. A Pack button does that when you ask.
  5. A task that no longer fits before 23:00 goes to a Not scheduled list. It's never deleted and never silently moved to tomorrow.
  6. Dragging back to where you started restores the day exactly.

Rule 4 surprised me. Closing gaps automatically felt like the planner was guessing. Leaving holes alone makes every move predictable.

How it is built

The planner is one pure function. It takes the day's items and a change, and returns the new layout. The page calls it on every pointer move, animates the cards to the previewed positions with CSS transforms, and commits the same result when you let go.

const result = plan(items, { id: 'brief', start: 10 * 60 })
result.items    // the whole day, re-laid out
result.shifted  // the tasks that were pushed later
result.tray     // the tasks that no longer fit

How I checked it

A fuzz test plays 50,000 random drags on random days and checks the rules after each one. It also compares every answer with a brute force version that scans the day in five minute steps. If a task is allowed to move earlier, or the tasks that follow get five extra minutes, the test fails.

The page is tested in Chromium and Firefox with a real mouse and keyboard, and the cards on screen are compared with the planner's answer. A Content-Security-Policy blocks requests to other sites. I haven't tested Safari or a real phone.

Try it

It's one 178 KB HTML file, MIT licensed, no account needed. The live page has a sample day, so drag "Write the brief" down to 10:00 and watch the rest move. The code is on GitHub.

What I'd like to hear: does "later only, no backfill" match how you expect a day to re-flow?

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.