Allows those with a passion for cooking to connect through a dedicated social media app. Users will be able to post new recipes, interact with other users' recipes, and search for other users/existing recipes based on their preferences.
- Category: Social networking
- Mobile: Designed strictly for mobile usage, allowing users to use their camera to take recipe photos in addition to viewing and interacting with recipe posts on the go.
- Story: Connects users with trending recipes and food inspiration. Users will be able to interact through the comments and voting system, which encourage a sense of community.
- Market: Anyone interested in food and cooking can use this app. Users are able to search for specific interests based on cuisine and diet.
- Habit: Users will open and use this app whenever they want to find or share recipe ideas and instructions. Users both consume (view recipes) and create (post recipes).
- Scope: Spice has a focus on posting and viewing recipes. The main feed acts as a trending page which allows users to interact with each other by reacting to recipe titles and photos.
Required Must-have Stories
- User sees app icon in home screen and styled launch screen
- User can sign up to create a new account (username, password, email, phone number)
- User can log in
- User can log out
- User stays logged in across restarts
- User can upload a photo, add an ingredient list, and recipe instructions
- User can either submit their post (through Parse) or cancel their submission
- User can view popular recipes on home page
- Users can add and view comments on a recipe
- Users can upvote/downvote a recipe
- User can tap a recipe photo to view a detailed recipe page
- User can view detailed information on a recipe (title, ingredient list, instructions)
- User can view personal username, profile picture, and number of posts
- User can view another user's username, profile picture, and number of posts
- User can search for recipes by keyword or user
- User can edit their profile picture
- User can change their username and password
- User can delete their account
Optional Nice-to-have Stories
- User can save posts made by other users and access them from inside the app
- User can edit an existing recipe
- User can pull to refresh
- User can load past posts infinitely
- Configure autolayout to standardize view on devices
- User can invite their contacts to join
- User can upload video for recipe instructions
- User can select their cuisine preferences when making an account
- User can set the cuisine type when uploading a post
- User can view recipes automatically configured to their set preferences during account creation
- User can view detailed recipes from the Edamam API
Here's a walkthrough of implemented user stores:
- Login Screen
- User can enter their username and password to log in
- Registration Screen
- User can sign up to create a new account (username, password, email, and phone number)
- Stream
- User can view the past recipes (photos and titles) and the author's profile picture and name
- User can upvote/downvote a recipe
- Users can view comments on a recipe
- Users can add a comment
- User can tap a recipe photo to view a detailed recipe page
- User can tap a profile picture to be brought to the desired user's profile page
- User can log out
- Creation
- User can upload a photo, add a recipe title, add an ingredient list/recipe
- Search
- User can search for recipes or users in a text bar
- User can view existing recipes from the Edamam API
- Other User Profile Screen
- User can view another user's username, profile picture, and number of posts
- User can view photos of recipes
- Personal Profile Screen
- User can view their username, profile picture, and number of posts
- User can view photos of recipes
- Detailed Recipe Screen
- User can view a title, ingredient list, and instructions for a specific recipe
- User can go back to the previous screen
- User Preferences Screen
- User can change their profile picture, username, and password
- User can log out
- User can delete their account
Tab Navigation (Tab to Screen)
- Home Screen
- Create a Recipe
- Search User/Recipe
- Personal Profile Screen
Flow Navigation (Screen to Screen)
- Login Screen => Registration Screen => Stream
- Registration Screen => Stream => Login Screen
- Stream => Detailed Recipe Screen => Other User Profile Screen
- Creation Screen => Stream
- Search Screen => Other User Profile Screen => Detailed Recipe Screen
- Other User Profile Screen => Detailed Recipe Screen
- Personal Profile Screen => User Preferences Screen => Detailed Recipe Screen
- Detailed Recipe Screen => Back to previous screen (Stream, Search Screen, User Profile Screen, Other User Profile Screen)
- User Preferences Screen => Login Screen
Property | Type | Description |
---|---|---|
username | String* | Username |
password | String* | Password |
String | User email | |
phoneNumber | String | User phone number |
profileImage | File | User profile picture |
numberOfPosts | Number | Total number of posts by a user |
createdAt | DateTime | Date when user is created (default field) |
updatedAt | DateTime | Date when user is last updated (default field) |
Property | Type | Description |
---|---|---|
objectID | String | Unique id for the user post (default field) |
author | Pointer (User) | Image author |
recipeName | String | Recipe title |
ingredientList | String | Recipe ingredients |
recipeSteps | String | Recipe procedure |
profileImage | Pointer (User) | Image of the user profile |
recipeImage | File | Recipe image that a user posts |
commentsCount | Number | Number of comments on a post |
comments | Pointer (Array) | Lists of comments on a post |
upvoteCount | Number | Number of upvotes on a post |
downvoteCount | Number | Number of downvotes on a post |
createdAt | DateTime | Date when post is created (default field) |
updatedAt | DateTime | Date when post is last updated (default field) |
Property | Type | Description |
---|---|---|
objectID | String | Unique id for the comment |
post | Pointer (Post) | Associated post |
text | String | Comment text |
author | Pointer (User) | Comment author |
createdAt | DateTime | Date when comment is created (default field) |
updatedAt | DateTime | Date when comment is last updated (default field) |
-
Login Screen:
- (Read/GET) User logs into app
- User can also create new profile
- (Read/GET) User logs into app
-
Registration Screen:
- (Create/POST) User signs up
-
Stream:
- (Read/Get) Read recipe name
- (Read/ GET) Read username
- (Read/GET) Get a picture of the recipe
- (Create/POST) Create an upvote on a post
- (Delete) Delete existing upvote
- (Create/POST) Create an downvote on a post
- (Delete) Delete existing downvote
- (Create/POST) Create a comment on a post
- (Delete) Delete existing comment
-
Creation:
- (Create/POST) Create the name of the recipe
- (Create/POST) Create ingredients' list of the recipe
- (Create/POST) Create recipe instructions
- (Create/POST) add a picture of the recipe
- (Create/POST) Submit the post
- (Delete) cancel the post
-
Search:
- (Read/GET) Search for the recipe
- (Read/GET) Search for the user
-
Other User Profile Screen:
- (Read/GET) Name of the user
- (Read/GET) Number of user's post
- (Read/GET) User's picture
- (Read/GET) Access detailed recipe by clicking picture objects
-
Profile Screen:
- (Read/GET) Query logged in user object
- (Read/GET) Number of user's post
- (Read/GET) User's picture
- (Read/GET) Access detailed recipe by clicking picture objects
-
Detailed Recipe Screen:
- (Read/GET) Name of the recipe
- (Read/GET) Ingredients of the recipe
- (Read/GET) Recipe instructions
-
Preferences Screen:
- (Update/PUT) Update user profile image
- (Update/PUT) Update Username
- (Update/PUT) Update Password
- (Delete/DELETE) Delete user profile
- (Create/POST) Lets a user log out
- Basic snippets for Parse network requests:
// (Read/GET) Query all posts where user is author
let query = PFQuery(className:"Post")
query.whereKey("author", equalTo: currentUser)
query.order(byDescending: "createdAt")
query.findObjectsInBackground { (posts: [PFObject]?, error: Error?) in
if let error = error {
print(error.localizedDescription)
} else if let posts = posts {
print("Successfully retrieved \(posts.count) posts.")
// TODO: Do something with posts...
}
}
// (Read/GET) Create a post
PFObject *post = [PFObject objectWithClassName:@"post"];
post[@"title"] = @"Green Eggs & Ham";
post[@"author"] = @"John Doe";
post[@"instructions"] = @"the most enlightening of instructions"
post[@"ingredients"] = @"the lovliest of ingredients"
[post saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
if (succeeded) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}];
// (Read/GET)
// Fetch posts for a user's home feed
PFQuery *query = [PFQuery queryWithClassName:@"post"];
[query whereKey:@"author" equalTo:@"John Doe"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(@"Successfully retrieved %d scores.", objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(@"%@", object.objectId);
}
} else {
// Log details of the failure
NSLog(@"Error: %@ %@", error, [error userInfo]);
}
}];
// (Delete/DELETE)
// Delete account
[PFObject deleteAllInBackground:objectArray block:^(BOOL succeeded, NSError * _Nullable error) {
if (succeeded) {
// The array of objects was successfully deleted.
} else {
// There was an error. Check the errors localizedDescription.
}
}];
// (Update/Put)
// Changing user's profile picture
PFQuery *query = [PFQuery queryWithClassName:@"user"];
// Retrieve the object by id
[query getObjectInBackgroundWithId:@"John Doe"
block:^(PFObject *user, NSError *error) {
// Now let's update it with some new data. In this case, profile picture
// will get sent to the cloud. Others haven't changed
user[@"username"] = @"xxDinoxx";
user[@"password"] = @"defSecure";
// keep going
[author saveInBackground];
}];