From 9e9e989830c56cb83eb857548410df2961a6381d Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Wed, 19 Feb 2025 22:41:18 +0100 Subject: [PATCH] initial release --- CHANGELOG.md | 9 ++++- common/components/GeminiApiComponent.php | 8 +++- common/models/Meal.php | 26 ++++++++++--- common/models/User.php | 2 +- common/models/search/MealSearch.php | 39 +++++++++++++++++++ .../m221203_160610_create_user_table.php | 2 +- .../m250219_133939_create_meal_table.php | 1 - frontend/controllers/MealController.php | 29 +++++--------- frontend/controllers/SiteController.php | 9 +---- frontend/models/SignupForm.php | 4 +- frontend/views/layouts/main.php | 6 +-- frontend/views/meal/index.php | 14 +++---- frontend/views/meal/upload.php | 2 +- frontend/views/site/index.php | 2 +- frontend/views/site/login.php | 2 - 15 files changed, 96 insertions(+), 59 deletions(-) create mode 100644 common/models/search/MealSearch.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bb1890..5e7391a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -* Initial release ## [0.1.0] - 2025-02-10 -* First release +This marks the first release! + +### Added + +* User is able to signup, reset password, and also receives a welcome email +* Able to upload from phone with the rear camera initially +* Confetti on success :) [Unreleased]: https://github.com/cgsmith/calorie/compare/0.0.1...HEAD [0.1.0]: https://github.com/cgsmith/calorie/releases/tag/0.1.0 \ No newline at end of file diff --git a/common/components/GeminiApiComponent.php b/common/components/GeminiApiComponent.php index 90aae04..7b4dce8 100644 --- a/common/components/GeminiApiComponent.php +++ b/common/components/GeminiApiComponent.php @@ -113,7 +113,6 @@ class GeminiApiComponent extends \yii\base\Component $meal = new Meal(); $gemini = json_decode($response->getContent(), true); - Yii::debug($gemini); $geminiMeal = json_decode($gemini['candidates'][0]['content']['parts'][0]['text'], true); $meal->protein = $geminiMeal['protein']; $meal->calories = $geminiMeal['calories']; @@ -121,8 +120,13 @@ class GeminiApiComponent extends \yii\base\Component $meal->fat = $geminiMeal['fat']; $meal->fiber = $geminiMeal['fiber']; $meal->food_name = $geminiMeal['food_name']; + $meal->user_id = Yii::$app->user->id; + $meal->file_name = $filePath; + Yii::debug($meal); + $meal->save(); + // @TODO catch unidentified pictures? - return $meal; + return $meal->id; } } diff --git a/common/models/Meal.php b/common/models/Meal.php index d263932..b27a5c2 100644 --- a/common/models/Meal.php +++ b/common/models/Meal.php @@ -2,6 +2,9 @@ namespace common\models; +use yii\behaviors\TimestampBehavior; +use yii\db\ActiveRecord; + /** * This is the model class for table "meal". * @@ -13,12 +16,11 @@ namespace common\models; * @property int $fat * @property int $carbohydrates * @property int $fiber - * @property int $meal * @property int $user_id * @property int $created_at * @property int $updated_at */ -class Meal extends \yii\db\ActiveRecord +class Meal extends ActiveRecord { public $base64File; @@ -31,14 +33,28 @@ class Meal extends \yii\db\ActiveRecord return 'meal'; } + + public function behaviors() + { + return [ + [ + 'class' => TimestampBehavior::class, + 'attributes' => [ + ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], + ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], + ], + ], + ]; + } + /** * {@inheritdoc} */ public function rules() { return [ - [['food_name', 'file_name', 'calories', 'protein', 'fat', 'carbohydrates', 'fiber', 'meal', 'created_at', 'updated_at'], 'required'], - [['user_id', 'calories', 'protein', 'fat', 'carbohydrates', 'fiber', 'meal', 'created_at', 'updated_at'], 'integer'], + [['food_name', 'file_name', 'calories', 'protein', 'fat', 'carbohydrates', 'fiber'], 'required'], + [['user_id', 'calories', 'protein', 'fat', 'carbohydrates', 'fiber', 'created_at', 'updated_at'], 'integer'], [['file_name'], 'string', 'max' => 255], ]; } @@ -56,10 +72,8 @@ class Meal extends \yii\db\ActiveRecord 'fat' => 'Fat', 'carbohydrates' => 'Carbohydrates', 'fiber' => 'Fiber', - 'meal' => 'Meal', 'created_at' => 'Created At', 'updated_at' => 'Updated At', ]; } - } diff --git a/common/models/User.php b/common/models/User.php index 4f6377d..4f1501c 100644 --- a/common/models/User.php +++ b/common/models/User.php @@ -89,7 +89,7 @@ class User extends ActiveRecord implements IdentityInterface public function rules() { return [ - ['status', 'default', 'value' => self::STATUS_VERIFIED], + ['status', 'default', 'value' => self::STATUS_ACTIVE], [['email'], 'email'], [['email'], 'unique'], [['sales_agent_id', 'created_at', 'updated_at'], 'integer'], diff --git a/common/models/search/MealSearch.php b/common/models/search/MealSearch.php new file mode 100644 index 0000000..1da4f70 --- /dev/null +++ b/common/models/search/MealSearch.php @@ -0,0 +1,39 @@ + $query, + ]); + + $this->load($params); + + // ALWAYS filter by user_id that is signed in + $query->andFilterWhere(['user_id' => Yii::$app->user->id]); + + if (!$this->validate()) { + return $dataProvider; + } + + + return $dataProvider; + } +} \ No newline at end of file diff --git a/console/migrations/m221203_160610_create_user_table.php b/console/migrations/m221203_160610_create_user_table.php index 8c6d42b..14c6f06 100644 --- a/console/migrations/m221203_160610_create_user_table.php +++ b/console/migrations/m221203_160610_create_user_table.php @@ -27,7 +27,7 @@ class m221203_160610_create_user_table extends Migration 'verification_token' => $this->string()->defaultValue(null), 'first_name' => $this->string(64), 'email' => $this->string()->notNull()->unique(), - 'status' => $this->smallInteger()->notNull()->defaultValue(User::STATUS_UNVERIFIED), + 'status' => $this->smallInteger()->notNull()->defaultValue(User::STATUS_ACTIVE), 'welcome_email_sent' => $this->boolean()->defaultValue(false), 'created_at' => $this->integer()->notNull(), 'updated_at' => $this->integer()->notNull(), diff --git a/console/migrations/m250219_133939_create_meal_table.php b/console/migrations/m250219_133939_create_meal_table.php index 88b84c0..3041a80 100644 --- a/console/migrations/m250219_133939_create_meal_table.php +++ b/console/migrations/m250219_133939_create_meal_table.php @@ -21,7 +21,6 @@ class m250219_133939_create_meal_table extends Migration 'fat' => $this->integer()->notNull(), 'carbohydrates' => $this->integer()->notNull(), 'fiber' => $this->integer()->notNull(), - 'meal' => $this->integer()->notNull(), 'user_id' => $this->integer()->notNull(), 'created_at' => $this->integer()->notNull(), 'updated_at' => $this->integer()->notNull(), diff --git a/frontend/controllers/MealController.php b/frontend/controllers/MealController.php index b3a64c1..bb01588 100644 --- a/frontend/controllers/MealController.php +++ b/frontend/controllers/MealController.php @@ -3,6 +3,7 @@ namespace frontend\controllers; use common\models\Meal; +use common\models\search\MealSearch; use frontend\models\MealForm; use Yii; use yii\data\ActiveDataProvider; @@ -51,22 +52,10 @@ class MealController extends Controller */ public function actionIndex() { - $dataProvider = new ActiveDataProvider([ - 'query' => Meal::find(), - /* - 'pagination' => [ - 'pageSize' => 50 - ], - 'sort' => [ - 'defaultOrder' => [ - 'id' => SORT_DESC, - ] - ], - */ - ]); + $searchModel = new MealSearch(); return $this->render('index', [ - 'dataProvider' => $dataProvider, + 'dataProvider' => $searchModel->search($this->request->queryParams), ]); } @@ -77,8 +66,8 @@ class MealController extends Controller if (Yii::$app->request->isPost) { $model->picture = UploadedFile::getInstance($model, 'picture'); if ($model->upload()) { - $meal = \Yii::$app->gemini->mealInquiry($model->filepath); - return $this->render('success', ['model' => $meal]); + $id = \Yii::$app->gemini->mealInquiry($model->filepath); + return Yii::$app->response->redirect(['meal/success', 'id' => $id]); } } @@ -87,9 +76,11 @@ class MealController extends Controller ]); } - public function actionSuccess() + public function actionSuccess($id) { - return $this->render('success'); + $model = $this->findModel($id); + + return $this->render('success', ['model' => $model]); } /** @@ -170,7 +161,7 @@ class MealController extends Controller */ protected function findModel($id) { - if (($model = Meal::findOne(['id' => $id])) !== null) { + if (($model = MealSearch::findOne(['id' => $id, 'user_id' => Yii::$app->user->id])) !== null) { return $model; } diff --git a/frontend/controllers/SiteController.php b/frontend/controllers/SiteController.php index 077d4d7..aec1ac4 100644 --- a/frontend/controllers/SiteController.php +++ b/frontend/controllers/SiteController.php @@ -144,8 +144,8 @@ class SiteController extends Controller { $model = new SignupForm(); if ($model->load(Yii::$app->request->post()) && $model->signup()) { - Yii::$app->session->setFlash('success', 'Thank you for registration! Snap your first meal.'); - return $this->response->redirect(['meal/create']); + Yii::$app->session->setFlash('success', 'Thank you for registering! Sign in and snap your first meal!'); + return $this->response->redirect(['meal/upload']); } return $this->render('signup', [ @@ -170,11 +170,6 @@ class SiteController extends Controller } - // @todo - // fix deployment script - // save local .env variables for deployment - // verify email is working - // fix user sales agent issue /** * Requests password reset. * diff --git a/frontend/models/SignupForm.php b/frontend/models/SignupForm.php index 4a91e74..09a276a 100644 --- a/frontend/models/SignupForm.php +++ b/frontend/models/SignupForm.php @@ -55,8 +55,8 @@ class SignupForm extends Model // the following three lines were added: $auth = \Yii::$app->authManager; - $salesAgentRole = $auth->getRole('user'); - $auth->assign($salesAgentRole, $user->getId()); + $userRole = $auth->getRole('user'); + $auth->assign($userRole, $user->getId()); return $this->sendEmail($user); } diff --git a/frontend/views/layouts/main.php b/frontend/views/layouts/main.php index 3552b1f..c346b18 100644 --- a/frontend/views/layouts/main.php +++ b/frontend/views/layouts/main.php @@ -48,13 +48,9 @@ $this->beginPage() ?> 'label' => 'Capture Meal', 'url' => [Url::to(['meal/upload'])], ]; - $menuItems[] = [ - 'label' => 'List Meals', - 'url' => [Url::to(['meal/index'])], - ]; $menuItems[] = [ 'label' => 'Summary', - 'url' => [Url::to(['summary'])], + 'url' => [Url::to(['meal/index'])], ]; } diff --git a/frontend/views/meal/index.php b/frontend/views/meal/index.php index 3b3b763..530e533 100644 --- a/frontend/views/meal/index.php +++ b/frontend/views/meal/index.php @@ -25,19 +25,15 @@ $this->params['breadcrumbs'][] = $this->title; 'dataProvider' => $dataProvider, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], - - 'id', - 'file_name', + 'food_name', 'calories', 'protein', 'fat', - //'carbohydrates', - //'fiber', - //'meal', - //'created_at', - //'updated_at', + 'carbohydrates', + 'fiber', + 'created_at:datetime', [ - 'class' => ActionColumn::className(), + 'class' => ActionColumn::class, 'urlCreator' => function ($action, Meal $model, $key, $index, $column) { return Url::toRoute([$action, 'id' => $model->id]); } diff --git a/frontend/views/meal/upload.php b/frontend/views/meal/upload.php index cbd307d..70d3f6b 100644 --- a/frontend/views/meal/upload.php +++ b/frontend/views/meal/upload.php @@ -51,7 +51,7 @@ $this->registerJS(" field($model, 'picture') ->fileInput([ 'class' => 'form-control', - //'capture' => 'environment', + 'capture' => 'environment', ]); ?>
diff --git a/frontend/views/site/index.php b/frontend/views/site/index.php index aed7083..102e141 100644 --- a/frontend/views/site/index.php +++ b/frontend/views/site/index.php @@ -16,7 +16,7 @@ $this->title = 'Calorie Thingy';

Track your food with a picture!

Capture a meal - View Summary

+ View Summary

diff --git a/frontend/views/site/login.php b/frontend/views/site/login.php index a52e0c4..cd7302e 100644 --- a/frontend/views/site/login.php +++ b/frontend/views/site/login.php @@ -41,8 +41,6 @@ $this->params['breadcrumbs'][] = $this->title;
If you forgot your password you can . -
- Need new verification email?