Original App Design Project - README
===
# Coupon Tracker
## Table of Contents
1. [Overview](#Overview)
1. [Product Spec](#Product-Spec)
1. [Wireframes](#Wireframes)
2. [Schema](#Schema)
## Overview
### Description
Ever wanted to purchase something for cheaper but couldn't find any deals? You might find a discount for some item that someone else wants, or vice versa. If everyone shared their coupons that they find in public, maybe you can get your hands on a bargain! With this app, you can find a coupon of your liking without the hassle of searching on your own. It is community driven, so you can help others help you.
### App Evaluation
- **Category:** Market
- **Mobile:** Android
- **Story:** Community-driven app that allows users to share and view coupons.
- **Market:** For users to want a discount on a certain product, or want to share any coupons they find in the public or web.
- **Habit:** Users can post throughout the day and select any coupons of their liking. They can also browse through categories and search any discounts from their local neighborhood.
- **Scope:** Rated E for Everyone
## Product Spec
### 1. User Stories (Required and Optional)
**Required Must-have Stories**
* User must register
* User must login
* User can view coupons
* User can view details of coupons
* User can post coupons
* User can delete their own coupons
**Optional Nice-to-have Stories**
* User can sort coupons
* User can favorite coupons
* User can report expired coupons
* User can see where the coupon is from
* Delete outdated coupons automatically
### 2. Screen Archetypes
* Register
* User must register
* Login
* User must login
* Coupon Stream
* User can view coupons
* User can sort coupons
* Delete outdated coupons automatically
* Details
* User can see type of coupon and what it's for
* User can see coupon price/percent discount
* User can inspect expiration date
* Compose/Post Coupons
* User can post coupons
* Favorites
* User can favorite coupons
* User can set reminder to use coupon (notification)
* Maps
* User can specify where the coupon is from
* Settings (EXTRA)
* User can set stream settings, like preferences for types of coupons
* User can set notification settings
### 3. Navigation
**Tab Navigation** (Tab to Screen)
* Coupon Stream (can split to API and Local)
* Favorites
* Maps
* Settings
**Flow Navigation** (Screen to Screen)
* Register
* Login
* Login
* Register
* Coupon Stream
* Coupon Stream
* Compose/Post Coupons
* Details
* Maps
* Favorites
* Favorites
* Details
* Maps
* Settings
* Compose/Post Coupons
## Wireframes
[Add picture of your hand sketched wireframes in this section]
<img src="YOUR_WIREFRAME_IMAGE_URL" width=600>
### [BONUS] Digital Wireframes & Mockups
### [BONUS] Interactive Prototype
## Schema
### Models
#### Coupon Post
| Property | Type | Description |
| ------------- | -------- | ------------|
| objectId | String | Unique id for the user post (default field) |
| username | Pointer | Image author |
| image | File | Image of coupon that user posts |
| description | String | Coupon description by author |
| likesCount | Int | Number of likes for the post |
| dislikesCount | Int | Number of dislikes for the post |
| createdAt | DateTime | Date when post is created (default field) |
| expirationDate| DateTime | Date when coupon will expire and post auto-deletes |
| favorite | Button | Allows user to favorite a coupon to view later |
| zipcode | Int | General area where coupon was found |
#### Coupon Post
| Property | Type | Description |
| ------------- | -------- | ------------ |
| userID | Int | Unique ID |
| username | String | Author Title |
| password | String | Password used to log in |
### Networking
#### List of Network Requests By Screen
- Login/Signup Screen
- (Create/POST) Create a new user on database
- Signing up
```java
// Create the ParseUser
ParseUser user = new ParseUser();
// Set core properties
user.setUsername("joestevens");
user.setPassword("secret123");
user.setEmail("email@example.com");
// Set custom properties
user.put("phone", "650-253-0000");
// Invoke signUpInBackground
user.signUpInBackground(new SignUpCallback() {
public void done(ParseException e) {
if (e == null) {
// Hooray! Let them use the app now.
} else {
// Sign up didn't succeed. Look at the ParseException
// to figure out what went wrong
}
}
});
```
- Logging in
```java
ParseUser.logInInBackground("joestevens", "secret123", new LogInCallback(){
public void done(ParseUser user, ParseException e) {
if (user = null) {
// Hooray! The user is logged in.
} else {
// Signup failed. Look at the ParseException to see what happened.
}
}
});
```
- Home Feed
- (Read/GET) Query all posts from local area
```java
// Define the class we would like to query
PostQuery<CouponItem> query = ParseQuery.getQuery(CouponItem.class);
// Define our query conditions
query.whereEqualTo("zipcode", ParseUser.getZipCode());
// Execute the find asynchronously
query.findInBackground(new FindCallback<CouponItem>() {
public void done(List<CouponItem> itemList, ParseException e) {
if (e == null) {
// Access the array of results here
String firstItemId = itemList.get(0).getObjectId();
Toast.makeText(CouponsActivity.this, firstItemId, Toast.LENGTH_SHORT).show();
} else {
Log.d("item", "Error: " + e.getMessage());
}
}
});
```
- (Create/POST) Favorite a post
- (Delete) Unfavorite a post
```java
FavoriteButton.onClick(new OnClickListener){
if(buttonIsInactive){
// set button status to active
// add pointer to post to signed in user profile
} else {
// set button status to inactive
// remove pointer to post from signed in user profile
}
}
```
- (Create/POST) React to a post
- (Delete) Unreact to a post
```java
LikeButton.onClick(new OnClickListener){
if(buttonIsInactive){
// set button status to active
// increment like counter
} else {
// set button status to inactive
// decrement like counter
}
}
DislikeButton.onClick(new OnClickListener){
if(buttonIsInactive){
// set button status to active
// increment dislike counter
} else {
// set button status to inactive
// decrement dislike counter
}
}
```
- Compose Screen
- (Create/POST) Add a new coupon object into the database
```java
private void postCoupon(String description, ParseUser currentUser, File photoFile) {
Coupon coupon = new Coupon();
coupon.setCode(code);
coupon.setDescription(description);
coupon.setImage(new ParseFile(photoFile));
coupon.setUser(currentUser);
coupon.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if (e != null) {
Log.e(TAG, "Error while saving", e);
Toast.makeText(getContext(), "Error while saving", Toast.LENGTH_SHORT).show();
} else {
Log.i(TAG, "Coupon was posted was successful!!");
}
}
});
}
```
- Details Screen
- (Read/GET) View additional coupon details
```java
```
- Profile Screen
- (Read/GET) View coupon posts and favorites from author
```java
// Define the class we would like to query
PostQuery<CouponItem> query = ParseQuery.getQuery(CouponItem.class);
// Define our query conditions
query.whereEqualTo("username", ParseUser.getCurrentUser());
// Execute the find asynchronously
query.findInBackground(new FindCallback<CouponItem>() {
public void done(List<CouponItem> itemList, ParseException e) {
if (e == null) {
// Access the array of results here
String firstItemId = itemList.get(0).getObjectId();
Toast.makeText(CouponsActivity.this, firstItemId, Toast.LENGTH_SHORT).show();
} else {
Log.d("item", "Error: " + e.getMessage());
}
});
```
- (Update/PUT) Edit coupon post from author
```java
```
- (Delete) Delete coupon post from author
```java
couponItem.deleteInBackground();
```
- (Delete) Unfavorite coupons from favorites list
```java
```
- [Add list of network requests by screen ]
- [Create basic snippets for each Parse network request]
- [OPTIONAL: List endpoints if using existing API such as Yelp]