Skip to content

mollyexten/flashy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

flashy

A flashcard app: https://flashy-app.netlify.app/


Overview

flashy is a mobile-first flashcard app. After signing up, users can create and modify their own flashcards, which are organized into decks. flashy can be used for increasing vocabulary or remembering terms and concepts in a specific subject.


MVP

The flashy MVP is a well-organized "React on Rails" RESTful web app. The backend is deployed on Heroku, and the frontend is deployed on Netlify. Backend endpoints and frontend API calls follow standard naming conventions. flashy includes a container component to reduce the number of API calls. The user interface facilitates full CRUD on the deck and entry tables and presents a uniform, responsive style.


Goals

Backend

  • Build a Ruby on Rails server with RESTful JSON endpoints
  • Build a database with three tables: users, decks, entries
  • The user to decks association will be one to many
  • The decks to entries association will be one to many
  • Index, show, and create controller methods for the decks table
  • Full CRUD controller methods for the entries table

Frontend

  • React app with one container component, seven screen components, two "component components" and two shared components
  • Set up axios calls for get and post on decks table
  • Set up axios calls for full CRUD on the entries table
  • Hold deck and entry information in state variables within the container component
  • Use both CSS Flexbox and Grid
  • Implement media queries for mobile and desktop

Libraries and Dependencies

Library Description
Create React App Sets up the tools needed for a React App
React Router DOM Enables linking and routing to different components
Axios Sends asynchronous HTTP requests to RESTful endpoints to perform CRUD on database
Ruby on Rails Backend frameword written in Ruby
PostgreSQL Imported as 'pg' in Rails, sets postgresql as the database for Active Record
rack-cors Handles cross-origin resource sharing, makes cross-origin AJAX possible
bcrypt Password hashing function for authentication
jwt Token-based authentication for tracking logged in users on frontend

Client (Front End)

Wireframes

Mobile Prototype

Mobile

signup signin

User home will display decks. Deck detail screens are the launching point for full CRUD on decks and entries.
homedeck

Some screens showing how post, update, and delete will work.
edit entrycreate deckcreate entry

Users will be able to review the term and details for each entry in the deck and navigate to different screens via the hamburger.
word front word back hamburger

In an earlier plan, editing the deck and its entries occurred in one screen. Not sure how this could be implemented, I decided against it. However, I still want to include this idea in case it is possible as a post-MVP.
deck manage create create/manage bottom

Desktop

signup signin

The same home and deck view on desktop:
home deck

Desktop CRUD:
edit entry create deck create entry

Reviewing entries:
word front word back

Desktop version of my "earlier plan" that I hope might be possible at some point:
deck manage create

Component Tree

Flashy Component Tree 1

Component Architecture


src
|__ assets/
      |__ fonts
      |__ icons
|__ components/
     |__ Deck
     |__ Entry
     |__ shared/
         |__ Layout
         |__ Nav
|__ containers
    |__ Flashcards
|__ screens/
    |__ DeckDetail
    |__ DeckForm
    |__ Decks
    |__ EntryDetail
    |__ EntryForm
    |__ SignIn
    |__ SignUp
|__ services/
    |__ apiConfig
    |__ decks
    |__ entries
    |__ users
|__ App.css
|__ App.js
|__ package.json

Time Estimates

Task Priority Estimated Time Time Invested Actual Time
Backend tables H 1 hr .5 hrs .5 hrs
Controllers & Models H 1 hr 3 hrs 3 hrs
Seed data H 1 hr 1.5 hrs 1.5 hrs
API calls H 2 hrs 2.5 hrs 2.5 hrs
App.js routing H 1 hr 1 hr 1 hr
Containers setup H 1 hr 2.5 hrs 2.5 hrs
Screens setup H 1 hr 1 hr 1 hr
Components, Layout H 1 hr .5 hrs .5 hrs
Layout H 1 hr 0 hrs 0 hrs
Nav - w/o auth H 2 hrs 2 hrs 2 hrs
SignUp H 2 hrs 2 hrs 2 hrs
SignIn H 2 hrs 1 hr 1 hr
SignOut H 2 hrs .5 hrs .5 hrs
Nav - w/ auth H 1 hr 2 hrs 2 hrs
Decks H 1 hr 1 hr 1 hr
Deck H 1 hr 1 hr 1 hr
DeckDetail H 2 hrs .5 hrs .5 hrs
Entry H 1 hr .5 hrs .5 hrs
Study H 2 hrs 4 hrs 4 hrs
DeckForm H 2 hrs 3 hrs 3 hrs
EntryForm H 2 hrs 3 hrs 3 hrs
Global styles (CSS) M 2 hrs 2 hrs 2 hrs
Grid (forms) M 2 hrs 3 hrs 3 hrs
Flex (decks/entries) M 2 hrs 2 hrs 2 hrs
Media queries M 2 hrs 2 hrs 2 hrs
Flip effect L 2 hrs 2 hrs 2 hrs
Deck sharing L 2 hrs 0 hrs 0 hrs
AWL deck generator L 2 hrs 0 hrs 0 hrs
Linting L 2 hrs 1.5 hrs 1.5 hrs
TOTAL 46 hrs 45.5 hrs 45.5 hrs

Server (Back End)

ERD Model

Flashy ERD


Post-MVP

  • Full CRUD for the decks table
  • Tablet media queries
  • Redirect create deck to create entry of same deck (perhaps with a "loading" screen in between)
  • Add password requirements to front page (6 characters or more)
  • Create invalid username and password messages
  • Deck sharing - Enable users to make decks public and search/share/save other users' decks
  • Flip effect - Animate entry detail screen so that the card "flips" between the term and its details
  • AWL Deck Generator - Include a textbox for pasting articles that will scan and produce a list of article words that are in the Academic Word List (AWL) and create a deck from these words

Code Showcase

I am proud of the conitional rendering that I did within the Flipcard component:

  return (
    <div
      className="flipcard-space"
      style={{ display: current === index ? "flex" : "none"}}
    >
    <div
        className="flipcard-div"
        onClick={handleClick}        
    >
        {front ? (
          <h3 className="term-side">{term}</h3>
        ) : (
          <p className="details-side">{details}</p>
        )} 
      </div>
      <p className="flipcard-count">{`${index+1}/${deck.length}`}</p>
    </div>
  );

Code Issues & Resolutions

  • To avoid getting too many "cannot read property ___ of null" errors, I learned to set up useEffects in this pattern: write the function first, then write a conditional ensuring the function only fires when the necessary variables actually exist. I had thought that the dependency array would automatically make sure no variables had null values, but that turned out not to be the case! Here is an example of a useEffect that uses this pattern:
useEffect(() => {
    if (currentUser) {
      fetchDecks();
    }
  }, [currentUser]);
  • My get request for entries turned out to be more difficult than I anticipated when I created the ERD. Since I wanted to get entries for just one user, the decks table had to serve as a through table. I modified the the user and entry models. For user:
has_many :entries, through: :decks

For entry:

has_one :user, through: :deck

And then, in the entries controller, I wrote this:

    @entries = @current_user.entries
    render json: @entries, status: :ok
  end

In the above snippet, @current_user comes from the verify method in the authentication controller.

  • The main route of my app - "/" - required authorization, so visitors would actually need to type in the url plus "/sign-up" to get started. In my App.js file, I placed this line before the main authorized route ("/"):
{!currentUser && <Redirect to={{pathname: "/sign-up", state: {from: location}}} />}

Then in "/sign-up", I added this to the top of the JSX portion:

{currentUser && <Redirect to={ location.state.from}/>}

The variable "location" is useLocation from react-router-dom. It helps keep track of the user's route path. This step was intended to keep users from just being redirected to the sign up screen if they refreshed their browser window. However, this made it impossible for new users to sign up and access the authorized content because "location" would be null in that case. As a quick fix, I changed the "/sign-up" portion to this:

{currentUser && <Redirect to="/" />}

This makes it possible for people to actually sign up and see the home screen. The one disadvantage to this method is that a logged in user, when refreshing their screen, will be redirected back to the decks screen no matter what screen they were viewing beforehand.

  • The last issue I encountered was a typo in my apiConfig.js file. Instead of writing "process.env.NODE_ENV", I had accidentally written "process.env.NODE_END". This made it so that my deployed front end only hoooked up to the local Rails server and could never hook up to the Heroku API.

About

A flashcard app

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published