TIM is the destination for productive life. On TIM, daily personal time spendings are recorded and displayed. Whether you're a student or a workholic, there's always a better way to be more productive.
- Category: Lifestyle
- Mobile: This app would be primarily developed for mobile. Functionality wouldn't be limited to mobile devices, however mobile version could potentially have more features.
- Story: Analyzes users' productivity.
- Market: Any individual could choose to use this app.
- Habit: This app can be used as often or unoften as the user wants depending on how accurately they want to measure their productivity.
- Scope: First we would start with user's daily routine by recording and generating reports based on these data.
Required Must-have Stories
- User can create an account.
- User logs in to access previous daily report
- User stays logged in across restarts
- User can logout
- Styled Launch Screen and App Icon
- User can add tasks on the calendar view
- User can select preset (study mode/breaktime/exercise...etc).
- App generates daily report based on these data. (See https://cocoapods.org/pods/Charts)
- Profile page for user.
- Settings to configure app options (Accesibility, Notification, General...etc).
- Calendar feature. (See https://cocoapods.org/pods/JTAppleCalendar)
Optional Nice-to-have Stories
- When user uses cell phone, time is recorded.
- Intuitive UI/UX to minimize user's interaction with app and still be able to generate accurate analysis on user's daily productivity.
- Gamified personal statistics on each activity.
- User can change password in the settings confifurations
- Login
- Register - User signs up or logs into their account
- Profile Screen - Allows user to upload weekly schedule or fill in information that is needed.
- Daily Report Screen - Allows user to check out daily reports.
Tab Navigation (Tab to Screen)
- Daily reports
- Profile
- Weekly schedule
Flow Navigation (Screen to Screen)
- Forced Log-in -> Account creation if no log in is available
- Weekly schedule creation :Text field to be modified.-> Jumps to preset :Text field to be modified.
- Profile -> Text field to be modified.
RxSwift
- (Optional) Reactive components & variables can be used to achieve better UX. (Check https://github.com/ReactiveX/RxSwift)
Property | Type | Description |
---|---|---|
author | Pointer to User | User who is being tracked |
activity | JSON Object | Type of activity and time spent |
username | string | Username of the use |
profile_picture | URL | URL of the user's profile picture |
Property | Type | Description |
---|---|---|
id | Integer | Unique id |
name | string | Name of the mode |
Property | Type | Description |
---|---|---|
mode | Mode | Mode of the logging |
timer | Integer | Time spending |
Property | Type | Description |
---|---|---|
author | Pointer to User | User who is being tracked |
objectId | String | unique ID for the user log |
image | file | image that user uploaded for profile image |
description | String | caption by author |
startedAt | DateTime | date when user started stopwatch |
endedAt | DateTime | date when user stopped stopwatch |
- GET - Authenticate the user
- POST - Sign up the user
- GET - Authenticate the user
- POST - Log the type of activity + start/end time
- READ/GET - Query logged in user object
- UPDATE - Update User Profile Image
- POST - Create event in calendar
- GET - Get events to show in calendar
- GET - Get activity times to build the chart
- GET - Get activity times to build the activity
- pinInBackground() - Once the local datastore is enabled, you can store an object by pinning it.
- fromLocalDatastore()/getObjectInBackground() - To get the data for a specific object.
let username = usernameTextField.text!
let password = usernameTextField.text!
PFUser.logInWithUsername(inBackground: username, password: password) { (user, error) in
if user != nil {
self.performSegue(withIdentifier: "loginSegue", sender: self)
} else {
print("Error: \(String(describing: error?.localizedDescription))")
}
}
let user = PFUser()
user.username = usernameTextField.text
user.password = usernameTextField.text
user.signUpInBackground { (success, error) in
if success {
self.performSegue(withIdentifier: "loginSegue", sender: self)
} else {
print("Error: \(String(describing: error?.localizedDescription))")
}
}
let logging = PFObject(className: "Logging")
let mode = (logging["mode"] as? [PFObject]) ?? []
mode["id"] = 1
mode["name"] = "Study Mode"
logging["timer"] = timer
logging.add(mode, forKey: "mode")
logging.saveInBackground { (success, error) in
if success {
print("Logging saved")
}
}
let gameScore = PFObject(className: "GameScore")
gameScore["score"] = 1337
gameScore["playerName"] = "AJ"
gameScore["studyMode"] = false
gameScore.pinInBackground()
let query = PFQuery(className:"GameScore")
query.from LocalDatastore()
quary.getObjectInBackground(withId:"codePath").continueWith{(task:
BFTask<PFOject>!)->Any? in
if task.error != nil {
return task
}
return task
}