YourCity is a platform to match people to their prefect city.

Related tags

Miscellaneousyourcity
Overview

YourCity

YourCity is a city matching App that matches users to their ideal city. It is a fullstack React App made with a Redux state manager and a backend using Python, Flask, SQL-Alchemy, and PostgresSQL.

Table of Contents
1. Features
2. Installation
3. Technical Implementation Details
4. Future Features
5. Contact
6. Special Thanks

Technologies

Features

Sign Up and Login Pages

Sign Up Login

Splash Page

Discover and search for new cities Feed Page

Features Splash Features

Profile

Profile card about user and view cities Profile

Feed Tab

YourCity feed displays all cities Feed Page

View, Add, Edit, and Delete Cities

Single city of name, photos, insights City Page

Add a City

follow

Cancel adding city

follow

Edit a city

Edit City

Create, Read, Update, Delete City Insights

View Insights

follow

Add Insights

follow

Edit Insights

follow

Installation

To build/run project locally, please follow these steps:

  1. Clone this repository
git clone https://github.com/{github-handle}/{app-name}.git
  1. Install Pipfile dependencies and create the virtual environment
pipenv install
  1. Install npm dependencies for the /react-app
cd react-app
npm install
  1. In the / root directory, create a .env based on the .env.example with proper settings

  2. Setup your PostgreSQL user, password and database and ensure it matches your .env file

  3. Before running any flask commands, confirm you are in the pipenv virtual env. If not, run the command:

pipenv shell
  1. In the root folder, create the database by running in the terminal:
flask db init
  1. In the root folder, migrate tables to the database by running in the terminal:
flask db migrate
  1. In the root folder, seed the database by running in the terminal:
flask seed all
  1. Start the flask backend in the / root directory
flask run
  1. Start the frontend in the /react-app directory
npm start

Technical Implementation Details

City Validators

This is the first project I used flask and SQLAlchemy, and I didn't have much experience using the wtform validators. After reading documentation, I created Forms to validate required fields with DataRequired and the length of fields with the Length class by providing a min and max.

Code snippet is shown here:

class CityPostForm(FlaskForm):
    name = StringField('name', validators=[DataRequired(), city_exists, Length(min=1, max=80)])
    state = StringField('state', validators=[Length(min=0, max=50)])
    thumbnail_img = StringField('thumbnail_img', validators=[Length(min=0, max=800)])
    description = StringField('description', validators=[Length(min=0, max=1200)])
    user_id = IntegerField('user_id', validators=[DataRequired()])

The form is created from the POST route to create a city, and it is validated using the validators above. If any fields throw an error, then the form.validate_on_submit() will fail and return the errors from form.errors. The resulting errors are passed into a custom error handler that sends back each of the errors to the frontend to display to the user, e.g. 'Field is required' or 'Name field must be between 0 and 100 characters in length'.

@city_routes.route('/', methods=['POST'])
@login_required
def city_post():
        form = CityPostForm()
        form['csrf_token'].data = request.cookies['csrf_token']
        if form.validate_on_submit():
            city = City()
            form.populate_obj(city)
            try:
                db.session.add(city)
                db.session.commit()
                return city.to_dict()
            except:
                return throw_server_error()
        return throw_validation_error(form.errors)

Read More for Long Posts (Insights)

Posts for insights are can span an entire page, which is not ideal for user experience. In order to limit the length, I created a Read More and Show Less buttons to conditionally render the entire post and to hide the post. I was able to use the scrollHeight and offsetHeight of the textarea input to determine if the text was overfilling the container. If the scroll is greater than the offset, then the post is longer and a Read More button should appear.

The frontend uses the isOverflow state to initially determine if the post is overflowing.

const [showMore, setShowMore] = useState(false);
const [isOverflow, setIsOverflow] = useState(true);

  
useEffect(() => {
  const scrollHeight = document.getElementById(`insight__text_id-${insight.id}`)?.scrollHeight;
  const offsetHeight = document.getElementById(`insight__text_id-${insight.id}`)?.offsetHeight;

  if (scrollHeight && offsetHeight) {
    if (scrollHeight > offsetHeight) {
      setShowMore(false);
    } else {
      setShowMore(true);
      setIsOverflow(false);
    }
  }
}, [insight.id]);

The showMore state is used to conditionally render a short post and the entire post. If showMore is false the component will render a cut off post that has a Read more click event to toggle the state. When the Read more is clicked, showMore is set to true and the component now renders the entire post.

In addition the isOverflow is used to render Show less only if the post is overfilling the container.

{!showMore &&
  <>
    <p>
      <span>
        { username }
      </span>
      { insight.insight }
    </p>
    <p className={styles.text_dots}>...</p>
    <span 
      onClick={() => setShowMore(true)}
    >
      Read more
    </span>
  </>
}
{showMore &&
  <>
    <p>
      <span>
        { username }
      </span>  
      { insight.insight }
    </p>
    {isOverflow &&
      <span 
        onClick={() => setShowMore(false)}
      >
        Show less
      </span>
    }
  </>
}

City Reducer

One of my goals on this project was to create a simple reducer with slices of state for each table. Taking code from one of my previous projects, I refactored the code to create four actions. The SET_CITY action case is used for updating the store for the CRUD operations of CREATE, UPDATE, and READ.

The reducer for my City table is shown below:

export default function reducer(state = {}, action) {
  let newState = { ...state };
  switch (action.type) {
    case SET_CITY:
      newState[action.city.id] = action.city;
      return newState;
    case SET_ALL_CITIES:
      action.cities.forEach(city => {
          newState[city.id] = city;
      });
      return newState;
    case DELETE_CITY:
      delete newState[action.cityId];
      return newState;
    case UNLOAD_CITIES:
      newState = {}
      return newState;
    default:
      return state;
  }
}

Future Features

  1. Matches - match people with cities based on their question responses

  2. Search - search cities

  3. Edit Profile - users edit profile info and add banner

Contact

Nico Pierson

[email protected]

Special Thanks

Owner
Nico G Pierson
Software Engineer passionate about open-source projects. Background in Python and JavaScript/React.js. When I don’t code, I travel and drink coffee.
Nico G Pierson
rTorrent Crash Prevention

rTorrent Disk Checker This program is capable of the following when: - a torrent is added by any program (autodl-irssi, RSS Downloader et

16 Dec 14, 2022
Buggy script to play with GPOs

GPOwned /!\ This is a buggy PoC I made just to play with GPOs in my lab. Don't use it in production! /!\ The script uses impacket and ldap3 to update

45 Dec 15, 2022
Demo content - Automate your automation!

Automate-AAP2 Demo Content - Automate your automation! A fully automated Ansible Automation Platform. Context Installing and configuring Ansible Autom

0 Oct 27, 2022
Simple python code for compile brainfuck program.

py-brainf*ck Just a basic compiled that compiles your brainf*ck codes and gives you informations about memory, used cells, dumped version, logs etc...

4 Jun 13, 2021
Configure request params such as text, color, size etc. And then download the image

Configure request params such as text, color, size etc. And then download the image

6 Aug 18, 2022
RestMapper takes the pain out of integrating with RESTful APIs.

python-restmapper RestMapper takes the pain out of integrating with RESTful APIs. It removes all of the complexity with writing API-specific code, and

Lionheart Software 8 Oct 31, 2020
This is a library to do functional programming in Python.

Fpylib This is a library to do functional programming in Python. Index Fpylib Index Features Intelligents Ranges with irange Lazyness to functions Com

Fabián Vega Alcota 4 Jul 17, 2022
Wrappers around the most common maya.cmds and maya.api use cases

Maya FunctionSet (maya_fn) A package that decompose core maya.cmds and maya.api features to a set of simple functions. Tests The recommended approach

Ryan Porter 9 Mar 12, 2022
🎴 LearnQuick is a flashcard application that you can study with decks and cards.

🎴 LearnQuick is a flashcard application that you can study with decks and cards. The main function of the application is to show the front sides of the created cards to the user and ask them to guess

Mehmet Güdük 7 Aug 21, 2022
Nag0mi ctf problem 2021 writeup

Nag0mi ctf problem 2021 writeup

3 Apr 04, 2022
A Python version of Canvacord

A copy of canvacord made in python! Installation Run any of these commands in terminal: Mac / Linux pip install canvacord Windows python -m pip insta

10 Mar 28, 2022
A Bot Which Can generate Random Account Based On Your Hits.

AccountGenBot This Bot Can Generate Account With Hits You Save (Randomly) Keyfeatures Join To Use Support Limit Account Generation Using Sql Customiza

DevsExpo 30 Oct 21, 2022
MinimalGearDisplay, Assetto Corsa app

MinimalGearDisplay MinimalGearDisplay, Assetto Corsa app. Just displays the current gear you are on. Download and Install To use this app, clone or do

1 Jan 10, 2022
Meower a social media platform written in Scratch 3.0 and Python

Meower Meower is a social media platform written in Scratch 3.0 and Python, ported to HTML for self-hosting. Try Beta 4.6 Changelog for 4.6 Start impl

Meower Media Co. 23 Dec 02, 2022
Apilytics for Python - Easy API analytics for Python backends

apilytics-python Installation Sign up and get your API key from https://apilytics.io - we offer a completely free trial with no credit card required!

Apilytics 6 Sep 29, 2022
TrackGen - The simplest tropical cyclone track map generator

TrackGen - The simplest tropical cyclone track map generator Usage Each line is a point to be plotted on the map Each field gives information about th

TrackGen 6 Jul 20, 2022
Scrapper For Paste.pics

PrntScScrapper Scrapper for Paste.pics If you are bored you can find some random screenshots from prnt.sc Features Saving screenshots Open in Browser

Fareusz 1 Dec 29, 2021
Repositório do programa ConstruDelas - Trilha Python - Módulos 1 e 2

ConstruDelas - Introdução ao Python Nome: Visão Geral Bem vinda ao repositório do curso ConstruDelas, módulo de Introdução ao Python. Aqui vamos mante

WoMakersCode 8 Oct 14, 2022
Python meta class and abstract method library with restrictions.

abcmeta Python meta class and abstract method library with restrictions. This library provides a restricted way to validate abstract methods. The Pyth

Morteza NourelahiAlamdari 8 Dec 14, 2022
Машинное обучение на ФКН ВШЭ

Курс "Машинное обучение" на ФКН ВШЭ Конспекты лекций, материалы семинаров и домашние задания (теоретические, практические, соревнования) по курсу "Маш

Evgeny Sokolov 2.2k Jan 04, 2023