One way to store daily appointments in a dictionary structure

Daily appointments

Abe Getzler

May 2020

Summary

This sample app shows one way to store daily appointments in a dictionary structure, using the sorted key facilities of the dictionary to arrange the appointments in chronological order.

Each day’s appointments dictionary is stored in TinyDB under date tag yyyyMMDD, one day per tag.

Sample runs

Here are two alternative ways to present the appointments, one using the common Am/PM format, and a second format using military time. I settled on the AM/PM format for external display, but used HHmm military format for dictionary keys internally for the sorting benefits.

Designer

The display is in three parts …

  1. Date selection and date level operations
  2. Single appointment creation and editing
  3. A ListView overview of the entire day’s appointments, sorted chronologically.

Component Events

When Screen1.Initialize

At startup, we prime our Date Picker to solicit a date for our schedule maintenance.

When DatePicker1 AfterDateSet

DatePicker1.Instant holds the selected date Instant. We format it into the Date Picker .Text to show it has been set properly. We call procedure refresh_elements to load up the ListView.Elements for that date’s schedule.

refresh_elements

This procedure calls procedure schedule_Elements to format the schedule_dict for the selected date.

schedule_Elements

This procedure accepts a schedule dictionary of the form

{“0055”:“wake up”,“0056”:“hunch”,“0100”:“go back to sleep”,“0954”:“brunch”,“1240”:“lunch”,“1247”:“munch”,“1900”:“supper”}

And formats its times with procedure AMPM.

During development, I tried to use a blank appointment text value as a signal to delete that HHmm key from the dictionary, but for some reason the deletion did not take. I glossed over that by skipping blank appointments when loading the ListView in procedure schedule_Elements. In a business application where blank appointments are kept empty for new appointments, that would be inappropriate.

AMPM

This gets an Instant from the HHmm military format, and formats that Instant using procedure HHMM_AMPM

HHMM_AMPM

Schedule_dict

This procedure returns the schedule dictionary for its given date Instant. If not found, it returns an empty dictionary. It looks in TinyDB under the tag returned by procedure TinyDB_tag based on the given date Instant.

TinyDB_tag

This date format was chosen to match the date pattern used in my button_calendar sample. This date format has the helpful property of matching alphabetic order and chronological order.

When btnClearThisDay.click

This button click event clears the schedule under tag TinyDB_tag for the current date, then calls refresh_elements to refresh the ListView.

When TimePicker1.AfterTimeSet

The Time Picker component is good for picking time values (HH:MM Instants), but its Instant value can’t be forced from a ListView selection. So I am using the .Text values of the Time Picker to hold the current hour and minute under discussion. (I dislike introducing global variables when I can avoid it, to avoid confusion about which data holder is in charge.)

Procedure HHMM_AMPM is used to format the chosen Instant for display.

When btnSave.Click

This event saved the currently displayed time and text into the appropriate key/value in today’s schedule, and saved that back into TinyDB. It calls schedule_dict to get the schedule from TinyDB. We format an HHMM version of the time from TimePicker1.Text using procedure HHmm, set the value in our schedule dictionary, and store it back into TinyDB. We then refresh our ListView Elements with refresh_Elements.

During development, I tried to use a blank appointment text value as a signal to delete that HHmm key from the dictionary, but for some reason the deletion did not take. I glossed over that by skipping blank appointments when loading the ListView. In a business application where blank appointments are kept empty for new appointments, that would be inappropriate.

HHmm

This procedure takes a time in the format 12:01 AM and formats it into military time format 0001 for use as a dict key. It separates out the three parts hh, mm, and AMPM then joins a reformatted hh (depending on the AMPM value) with the mm part. It uses helper procedures AM_HH and PM_HH for the two differing problems of AM and PM hour formatting.

AM_HH

In the morning, 12 AM is 00 hours military time, other hours are unchanged.

PM_HH

In the afternoon, 12 PM is unchanged, otherwise add 12 to afternoon hours to get military hours.

When ListView1.AfterPicking

Selecting an appointment from ListView1 copies its parts (time and text) into TimePicker1.Text and txbAppointment.Text. The parts are surrounding the ‘ | ‘ in the Selection.

Setting the TimePicker1 Instant is tricky. I use procedure timeInstant to format it from the display format hh:mm AMPM.

timeInstant

To generate a time Instant from its input, it must use either procedure AM_HH or procedure PM_HH to feed the hour into Clock1.MakeTime.

Gallery Link

ai2.appinventor.mit.edu/?galleryId=6361588663975936

More Projects

4 Likes

Hello @ABG,
if it wouldn't be too much trouble, could you please post the .aia file here? I am trying to wrap my head around how this works, so it would be helpful to be able to download the code.
Thanks in advance,
Dan :smiley_cat:

A link to the gallery is provided. Click on it, then in the gallery click on:

Load App Into MIT App Inventor

Why do we need the date picker if we don’t see it in the list?

This particular scheduler was set up to show only one date at a time, the date chosen in the date picker.

Feel free to extend it to include date ranges in a ListView, to allow surveying an entire week at a time.

Which block should I join the date?

Join the date for what purpose?

Oh, I see now why I shouldn't have included the date. I apologize for the confusion earlier. I had thought that each item on the list was from a different day. Your method is much simpler. Sorry to have troubled you.

It doesn't save the list

What doesn't save what list?

P.S. I notice the refresh_Elements procedure replaces the Elements of the ListView, but it does not have the more modern ListView block to refresh the ListView display off its Elements.

(That block was added after this tutorial was written, along with ListView image support.)

Is that what you are experiencing?