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
Metal Gear Rising: Revengeance's DAT archive (un)packer

DOOMP Metal Gear Rising: Revengeance's DAT archive (un)packer

Christopher Holzmann Pérez 5 Sep 02, 2022
An OrpheusDL Tidal module

OrpheusDL - Tidal A Tidal module for the OrpheusDL modular archival music program Report Bug · Request Feature Table of content About OrpheusDL - Tida

Daniel 54 Dec 29, 2022
Repository for 2021 Computer Vision Class @ Chulalongkorn University

2110443 - Computer Vision (2021/2) Computer Vision @ Chulalongkorn University Anaconda Download Link https://www.anaconda.com/download/ Miniconda and

Chula PIC Lab 5 Jul 19, 2022
Voldemort's Python import helper

importmagician Voldemort's Python import helper pip install importmagician Import from uninstalled Python directories Say you have a directory (relat

Zhengyang Feng 4 Mar 09, 2022
A calculator developed in Python.

Calculadora Uma simples calculadora... ( + − × ÷ ) 💻 Situação do projeto: Projeto finalizado ✔️ 🛠 Tecnologias: Python Tkinter (GUI) ⚙️ Pré-requisito

Arthur V.B.S. 1 Jan 27, 2022
Very simple encoding scheme that will encode data as a series of OwOs or UwUs.

OwO Encoder Very simple encoding scheme that will encode data as a series of OwOs or UwUs. The encoder is a simple state machine. Still needs a decode

1 Nov 15, 2021
A powerful and user-friendly binary analysis platform!

angr angr is a platform-agnostic binary analysis framework. It is brought to you by the Computer Security Lab at UC Santa Barbara, SEFCOM at Arizona S

6.3k Jan 02, 2023
Write Streamlit apps using Notion! (Prototype)

Streamlit + Notion test app Write Streamlit apps using Notion! ☠️ IMPORTANT: This is just a little prototype I made to play with some ideas. Not meant

Thiago Teixeira 22 Sep 08, 2022
The Blinker Herald includes helpers to easily emit signals using the excellent blinker library.

Blinker Herald The Blinker Herald includes helpers to easily emit signals using the excelent blinker library. Decorate a function or method with @blin

SatelliteQE 7 Nov 03, 2022
SHF TEST BACKEND

➰ SHF TEST BACKEND ➿ 🐙 Goals Dada una matriz de números enteros. Obtenga el elemento máximo en la matriz que produce la suma más pequeña al agregar t

Wilmer Rodríguez S 1 Dec 19, 2021
Pre-crisis Risk Management for Personal Finance

Антикризисный риск-менеджмент личных финансов Риск-менеджмент личных финансов условиях санкций и/или финансового кризиса: делаем сегодня все, чтобы за

Dmitry Petukhov 593 Jan 09, 2023
Minos-python - A framework which helps you create reactive microservices in Python

minos-python Summary [TODO] Packages minos-microservice-aggregate minos-microser

Minos Framework 380 Jan 04, 2023
A Python module for decorators, wrappers and monkey patching.

wrapt The aim of the wrapt module is to provide a transparent object proxy for Python, which can be used as the basis for the construction of function

Graham Dumpleton 1.8k Jan 06, 2023
Zapiski za ure o C++-u

cpp-notes Zapiski o C++-u. Objavljena verzija je na https://e6.ijs.si/~jslak/c++/ Generating the notes The setup assumes you are working in a Linux en

Jure Slak 1 Jan 05, 2022
A python implementation of differentiable quality diversity.

Differentiable Quality Diversity This repository is the official implementation of Differentiable Quality Diversity.

ICAROS 41 Nov 30, 2022
Remove Sheet Protection from .xlsx files. Easily.

🔓 Excel Sheet Unlocker Remove sheet protection from .xlsx files. How to use Run Run the script/packaged executable from the command line. Universal u

Daniel 3 Nov 16, 2022
decorator

Decorators for Humans The goal of the decorator module is to make it easy to define signature-preserving function decorators and decorator factories.

Michele Simionato 734 Dec 30, 2022
Render your templates using .txt files

PizzaX About Run Run tests To run the tests, open your terminal and type python tests.py (WIN) or python3 tests.py (UNX) Using the function To use the

Marcello Belanda 2 Nov 24, 2021
Generates Windows 95 and 95 OEM keys using the modulus 7 check algorithm

w95keygen-python windowskeygen.py - Generates Windows 95 and 95 OEM keys using the modulus 7 check algorithm Just download and drop in the directory y

Joshua Alto 1 Dec 06, 2021
A Non profit app built on top of Frappe framework & ERPNext

Non Profit A Non profit app built on top of Frappe framework & ERPNext. People who change the world need the tools to do it! The Non Profit Modules of

Frappe 16 Nov 17, 2022