Skip to content

MongoDB, Express, React, Node stack user-to-user service to help relocation.

Notifications You must be signed in to change notification settings

jsadsad/HaulAway

Repository files navigation

HaulAway

Summary

HaulAway is a user-to-user service that helps alleviate the difficulties of moving haul from one destination to the next.

We all know the struggles of moving. It takes a considerable amount of time signing up for moving services and find out the right vehicle sizes and price plans. With HaulAway, we make that simpler.

In this fullstack application, every information is stored in our NoSQL document-oriented Mongo database. Express is used for our backend routing to simplify the task of writing server code. React is the tool used for creating dynamic and scalable views rendered in HTML. Lastly with Node, JavaScript is able to be implemented in the backend used to handle server-side requests.

Logo

Home Page

The Brilliant Team

Joshua C. Sadsad: Lead

Lena Shin: Backend

Fabio R. Bortone: Frontend

Dmitrii An: Flex

Technologies Used

Backend Frontend
MongoDB React
Express google-maps-react
Node react-google-autocomplete
multer react-geocode
AWS S3 geolib

Features

  1. User Auth

The HaulAway team implemented a User Authentication system to access the job form and display the respective job in an index. Users are required to upload a profile picture that stores into our AWS S3 bucket.

User Auth

User Example

  1. Job Postings

Users have to submit a form with required fields such as pickup, destination, start date, and end date. These fields are required to pass validations in order to submit a job.

In the Job Index, only available jobs are shown through a selector.

export const getAvailableJobs = (state) => {
  return Object.values(state.entities.jobs).filter((job) => job.isAvailable)
}

User Example

  1. Google Maps

Googles Maps is dynamically supported to show where a destination or pickup can be depending on the route. A Circle prop is included in the map to help visualize the location.

On the job form, there is a default location until the Destination is submitted. Using geolib, distance is calculated from Pickup to Destination. Once distanced is obtained, a price is also able to be generated and stored within every new Job.

  onDestinationSelected(place) {
    const address = place.formatted_address,
      latValue = place.geometry.location.lat(),
      lngValue = place.geometry.location.lng()
    this.setState({
      destinationCoords: {
        lat: latValue,
        lng: lngValue,
      },
      destination: address ? address : '',
      markerPosition: {
        lat: latValue,
        lng: lngValue,
      },
      mapPosition: {
        lat: latValue,
        lng: lngValue,
      },
    })
  }

Job Form

  1. AWS

Users have the ability to upload multiple photos at once and images are uniquely stored in the MongoDB Collection.

router.post('/uploads', upload.array('file', 12), (req, res) => {
  const file = req.files
  let s3bucket = new AWS.S3({
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    region: process.env.AWS_REGION,
  })
  s3bucket.createBucket(function () {
    let ResponseData = []

    file.map((item) => {
      let params = {
        Bucket: process.env.AWS_BUCKET_NAME,
        Key: item.originalname,
        Body: item.buffer,
        ACL: 'public-read',
      }
      s3bucket.upload(params, function (err, data) {
        if (err) {
          res.json({ error: true, Message: err })
        } else {
          ResponseData.push(data)
          if (ResponseData.length == file.length) {
            res.json({
              Message: 'File Uploaded successfully',
              Data: ResponseData,
            })
          }
        }
      })
    })
  })
})

Job Index

  1. Reviews

Once 2 Users (1 Job Poster and 1 Job Taker) have interacted and closed a job, they now have the ability to review each other. Reviews are able to be updated or deleted.

  reviewJobButtons() {
    const job = this.props.job
    if (!job.reviews.includes(this.props.currentUserId)) {
      if (
        (job.jobPoster._id === this.props.currentUserId ||
          job.jobTaker === this.props.currentUserId) &&
        job.isClosed
      ) {
        return (
          <div className="review-job-buttons">
            <div className="review-buttons-title">
              Would you like to review this transaction?
            </div>
            <div className="review-job-buttons-inner-wrap">
              <Link to={`/jobs/${job._id}/review`} job={job}>
                <button className="yes-review-button">YES</button>
              </Link>
              <button
                className="no-review-button"
                onClick={(e) => this.handleClick('noReviewJob', e)}
              >
                NO
              </button>
            </div>
          </div>
        )
      }
    }
  }

Review Form

Future Incorporations

  • User Average Ratings
  • Calculate Fees Depending on Distance
  • User Private Messaging

References Used

Why-Use-MongoDB

Uploading-to-S3

HTML Entities

About

MongoDB, Express, React, Node stack user-to-user service to help relocation.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •