Giter Club home page Giter Club logo

coach_scheduler's Introduction

scheduler

Dependencies

The core dependencies are:

  • Ruby 2.5
  • rails
  • bootstrap
  • webpacker
  • graphql
  • postgres

Development dependencies:

Testing dependencies:

Running the app

To run the app locally, ensure you have Ruby 2.5.3 installed. If not, it can be installed using rbenv:

rbenv install 2.5.3

Issue the following from the project root to set up the project and start the app on port 3000.

bin/setup

The app is also deployed at jmromer-booking.herokuapp.com.

Scope

The app provides a web-based UI for a single user to book appointments with coaches.

The following assumptions were made to limit scope:

  • The app is meant to be used by a single user / "coachee"
  • No authentication is needed
  • No UI for coaches to input availability needed (realistically this would be desirable)
  • Provided seed data provides weekly recurring availability
  • Provided seed data represents one month of recurring availability
  • When an appointment is booked, that time slot is left in the availability list in order to demo some error handling

Design

UI

The booking UI is at the root url, the appointment-listing interface at /appointments. Each is managed by a stateful React component, BookingApp and AppointmentsList, respectively. As much as possible, I used functional components for presentational concerns.

Client-side logic

API query functions are defined in app/javascript/lib/api.js.

Application logic

# config/routes.rb

post "/graphql", to: "graphql#execute"
config/routes.rb L8 (master)

GraphQL Schema

# app/graphql/scheduler_schema.rb

class SchedulerSchema < GraphQL::Schema
  mutation Types::MutationType
  query Types::QueryType
end
app/graphql/scheduler_schema.rb L3-6 (master)

Mutations

The handler for requests creating a booking is defined in app/graphql/mutations/reserve_availability.rb

Queries

See app/graphql/types/query_type.rb for the root query definitions.

Database schema

The Rails application defines three models: Appointment, Availability, and Coach. A coach record is one-to-many-associated with both appointments and availabilities (independently).

Since it seems likely that in practice an application like this would need a way for coaches to enter their availability, the seed data was used to generate and persist availability time slots within the given intervals. (In contrast to persisting the provided times and computing availability on a per-request basis.)

Timezones

All dates and times are normalized to UTC when persisted to the database, but presented to the user as localized in the coach's approximate timezoneโ€ .

Some presentational localization methods are defined in LocalizationMixin. I opted to include this module directly in the ApplicationRecord models rather than using presenter objects since the logic is minimal.

โ€ approximate because UTC offsets don't map perfectly to timezones due to DST. A more robust approach would be to parse the timezone labels provided in the seed data and mapping these to normalized timezone labels.

Appointment Booking

Appointments can be booked from an availability record by invoking Availability#book_appointment!, which destroys the given availability record and creates the corresponding appointment in a transaction. The logic here is just minimal enough that an OO approach seems kosher--for anything more complicated I'd opt for a service object / transaction script.

# app/models/availability.rb

def book_appointment!
  transaction do
    appointment =
      coach
        .appointments
        .create(start_dt: start_dt, end_dt: end_dt)
    destroy
    appointment
  end
end
app/models/availability.rb L11-20 (master)

Availability generation

The class method Availability.build_attrs_within_range generates an array of hashes, each with the attributes of an Availability record to be persisted. This could be refactored to be more idiomatic for Ruby, but a bare loop will do in a pinch.

# app/models/availability.rb

# Given a specific coach, a day of the week, and start and end times in
# coach's local time, build an array of Availability attribute-hashes suitable
# for persisting, where each attribute hash represents an availability
# timeslot of duration `interval_length_mins` (default: 30 minutes).
#
# Unless a `number_of_weeks` argument is provided, default to a non-recurring
# schedule.
#
# Keyword Arguments:
#
#    coach [Coach]
#    day_of_week [String]: "Wednesday"
#    local_start_time [String]: "05:00AM"
#    local_end_time [String]: "10:00AM"
#    interval_length_mins [Integer]: 30 (default)
#    number_of_weeks [Integer]: 1 (default)
#
# Returns (example):
#
#    [
#      {
#        coach_id: 1,
#        start_dt: <Thu, 07 Feb 2019 22:30:00 UTC +00:00>,
#        end_dt: <Thu, 07 Feb 2019 23:00:00 UTC +00:00>
#      },
#      {. . .},
#    ]
#
app/models/availability.rb L24-51 (master)

Tests

Issues bin/rails spec from the project root to the run the test suite. Presently only RSpec tests are written.

Notes on style:

  • Mostly xUnit four-phase style, I try to leverage the RSpec DSL minimally.
  • Not much need for mocking and stubbing or VCR recording in this suite, but I do build persistence objects stubbed, where feasible (see spec/models/availability_spec.rb)
  • Request specs are defined in spec/queries/coach_queries_spec.rb
  • I ran out of time, but the next thing I'd add is React component tests in Enzyme and more server-side testing around the reserveAvailability mutation.

coach_scheduler's People

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.