Got it working! 🍎
This commit is contained in:
128
common/components/GeminiApiComponent.php
Normal file
128
common/components/GeminiApiComponent.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace common\components;
|
||||
|
||||
use common\models\Meal;
|
||||
use Exception;
|
||||
use Yii;
|
||||
use yii\helpers\FileHelper;
|
||||
use yii\httpclient\Client;
|
||||
|
||||
class GeminiApiComponent extends \yii\base\Component
|
||||
{
|
||||
public Client $client;
|
||||
public string $apiKey;
|
||||
public string $baseUrl;
|
||||
public string $model;
|
||||
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->client = new Client([
|
||||
'baseUrl' => $this->baseUrl,
|
||||
'requestConfig' => [
|
||||
'format' => Client::FORMAT_JSON
|
||||
],
|
||||
'responseConfig' => [
|
||||
'format' => Client::FORMAT_JSON
|
||||
],
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function mealInquiry($filePath)
|
||||
{
|
||||
$data = [
|
||||
"contents" => [
|
||||
[
|
||||
"role" => "user",
|
||||
"parts" => [
|
||||
[
|
||||
"text" => "INSERT_INPUT_HERE"
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"role" => "user",
|
||||
"parts" => [
|
||||
[
|
||||
"inline_data" => [
|
||||
"data" => base64_encode(file_get_contents($filePath)),
|
||||
"mimeType" => FileHelper::getMimeType($filePath)
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"systemInstruction" => [
|
||||
"role" => "user",
|
||||
"parts" => [
|
||||
[
|
||||
"text" => "Provide a caloric and macro estimate for pictures I provide to you. Try to be as accurate as possible and always calculate the everything you see in the picture. Proivde a 3 or 4 word `food_name`"
|
||||
]
|
||||
]
|
||||
],
|
||||
"generationConfig" => [
|
||||
"temperature" => 1,
|
||||
"topK" => 40,
|
||||
"topP" => 0.95,
|
||||
"maxOutputTokens" => 1000,
|
||||
"responseMimeType" => "application/json",
|
||||
"responseSchema" => [
|
||||
"type" => "object",
|
||||
"properties" => [
|
||||
"food_name" => [
|
||||
"type" => "string"
|
||||
],
|
||||
"calories" => [
|
||||
"type" => "integer"
|
||||
],
|
||||
"protein" => [
|
||||
"type" => "integer"
|
||||
],
|
||||
"fat" => [
|
||||
"type" => "integer"
|
||||
],
|
||||
"carbohydrates" => [
|
||||
"type" => "integer"
|
||||
],
|
||||
"fiber" => [
|
||||
"type" => "integer"
|
||||
]
|
||||
],
|
||||
"required" => [
|
||||
"food_name",
|
||||
"calories",
|
||||
"protein",
|
||||
"fat",
|
||||
"carbohydrates",
|
||||
"fiber"
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$response = $this->client
|
||||
->post([$this->model, 'key' => $this->apiKey])
|
||||
->setData($data)
|
||||
->send();
|
||||
|
||||
if ($response->statusCode != 200) {
|
||||
throw new Exception('There was an issue with the AI side of things - sorry! It is a MVP after all :/');
|
||||
}
|
||||
|
||||
$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'];
|
||||
$meal->carbohydrates = $geminiMeal['carbohydrates'];
|
||||
$meal->fat = $geminiMeal['fat'];
|
||||
$meal->fiber = $geminiMeal['fiber'];
|
||||
$meal->food_name = $geminiMeal['food_name'];
|
||||
|
||||
return $meal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,469 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace common\components;
|
||||
|
||||
use common\jobs\EmailJob;
|
||||
use common\models\Account;
|
||||
use common\models\InvoiceItem;
|
||||
use common\models\SalesAgent;
|
||||
use common\models\Service;
|
||||
use Yii;
|
||||
use yii\helpers\Url;
|
||||
use yii\httpclient\Client;
|
||||
use yii\httpclient\Request;
|
||||
use yii\httpclient\RequestEvent;
|
||||
|
||||
class SonarApiComponent extends \yii\base\Component
|
||||
{
|
||||
public Client $client;
|
||||
public string $baseUrl;
|
||||
public string $bearerToken;
|
||||
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->client = new Client([
|
||||
'baseUrl' => $this->baseUrl,
|
||||
'requestConfig' => [
|
||||
'format' => Client::FORMAT_JSON
|
||||
],
|
||||
'responseConfig' => [
|
||||
'format' => Client::FORMAT_JSON
|
||||
],
|
||||
]);
|
||||
|
||||
// Setup event for auth before each send
|
||||
$this->client->on(Request::EVENT_BEFORE_SEND, function (RequestEvent $event) {
|
||||
$event->request->addHeaders(['Authorization' => 'Bearer ' . $this->bearerToken]);
|
||||
});
|
||||
}
|
||||
|
||||
public function getAccounts(int $page = 1, int $limit = 100)
|
||||
{
|
||||
$data = [
|
||||
'form_params' => [
|
||||
'query' => 'query accountsWithSalesAgents(
|
||||
$paginator: Paginator,
|
||||
$search: [Search],
|
||||
$sorter: [Sorter]
|
||||
) {
|
||||
accounts(
|
||||
paginator: $paginator
|
||||
search: $search
|
||||
sorter: $sorter
|
||||
reverse_relation_filters: {
|
||||
relation: "custom_field_data",
|
||||
search: {
|
||||
integer_fields: {
|
||||
attribute: "custom_field_id",
|
||||
search_value: 12,
|
||||
operator: EQ
|
||||
}
|
||||
}
|
||||
}
|
||||
general_search_mode: ROOT_PLUS_RELATIONS
|
||||
account_status_id: 1
|
||||
) {
|
||||
entities {
|
||||
id
|
||||
name
|
||||
account_status {
|
||||
id
|
||||
name
|
||||
}
|
||||
account_services {
|
||||
entities {
|
||||
id
|
||||
quantity
|
||||
name_override
|
||||
price_override
|
||||
price_override_reason
|
||||
service {
|
||||
id
|
||||
name
|
||||
amount
|
||||
enabled
|
||||
application
|
||||
type
|
||||
}
|
||||
}
|
||||
page_info {
|
||||
page
|
||||
records_per_page
|
||||
total_count
|
||||
total_pages
|
||||
}
|
||||
}
|
||||
custom_field_data(custom_field_id:12) {
|
||||
entities {
|
||||
id
|
||||
custom_field_id
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
page_info {
|
||||
page
|
||||
records_per_page
|
||||
total_count
|
||||
total_pages
|
||||
}
|
||||
}
|
||||
}',
|
||||
'variables' => [
|
||||
'paginator' => [
|
||||
'page' => $page,
|
||||
'records_per_page' => $limit
|
||||
],
|
||||
'search' => [],
|
||||
'sorter' => [
|
||||
[
|
||||
'attribute' => 'updated_at',
|
||||
'direction' => 'ASC',
|
||||
]
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$response = $this->client->createRequest()
|
||||
->setMethod('POST')
|
||||
->setData($data)
|
||||
->send();
|
||||
|
||||
$account = json_decode($response->getContent(), true);
|
||||
|
||||
return $account['form_params']['data'];
|
||||
}
|
||||
|
||||
public function getInvoices(string $startDate, string $endDate)
|
||||
{
|
||||
$page = 1;
|
||||
$limit = 100;
|
||||
$invoices = [];
|
||||
do {
|
||||
$data = [
|
||||
'form_params' => [
|
||||
'query' => 'query accountInvoice($paginator: Paginator, $search: [Search], $sorter: [Sorter]) {
|
||||
invoices(
|
||||
paginator: $paginator
|
||||
search: $search
|
||||
sorter: $sorter
|
||||
general_search_mode: ROOT_PLUS_RELATIONS
|
||||
) {
|
||||
entities {
|
||||
id
|
||||
account_id
|
||||
total_debits
|
||||
void
|
||||
remaining_due
|
||||
date
|
||||
due_date
|
||||
end_date
|
||||
delinquent
|
||||
debits {
|
||||
entities {
|
||||
id
|
||||
quantity
|
||||
service_id
|
||||
service_name
|
||||
amount
|
||||
}
|
||||
}
|
||||
credits {
|
||||
entities {
|
||||
amount
|
||||
}
|
||||
}
|
||||
}
|
||||
page_info {
|
||||
page
|
||||
records_per_page
|
||||
total_count
|
||||
total_pages
|
||||
}
|
||||
}
|
||||
}',
|
||||
'variables' => [
|
||||
'paginator' => [
|
||||
'page' => $page,
|
||||
'records_per_page' => $limit
|
||||
],
|
||||
'search' => [
|
||||
[
|
||||
'date_fields' => [
|
||||
['attribute' => 'date', 'search_value' => $startDate, 'operator' => 'GTE'],
|
||||
['attribute' => 'date', 'search_value' => $endDate, 'operator' => 'LTE'],
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
],
|
||||
'sorter' => [
|
||||
[
|
||||
'attribute' => 'updated_at',
|
||||
'direction' => 'ASC',
|
||||
]
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
$response = $this->client->createRequest()
|
||||
->setMethod('POST')
|
||||
->setData($data)
|
||||
->send();
|
||||
|
||||
|
||||
$responseData = json_decode($response->getContent(), true);
|
||||
$invoices = array_merge($invoices, $responseData['form_params']['data']['invoices']['entities']);
|
||||
$page++;
|
||||
} while ($page < ($responseData['form_params']['data']['invoices']['page_info']['total_pages'] + 1));
|
||||
|
||||
return $invoices;
|
||||
}
|
||||
|
||||
public function getInvoice(int $invoiceId = 1)
|
||||
{
|
||||
$page = 1;
|
||||
$limit = 100;
|
||||
$data = [
|
||||
'form_params' => [
|
||||
'query' => 'query accountInvoice($paginator: Paginator, $search: [Search], $sorter: [Sorter]) {
|
||||
invoices(
|
||||
id: ' . $invoiceId . '
|
||||
paginator: $paginator
|
||||
search: $search
|
||||
sorter: $sorter
|
||||
general_search_mode: ROOT_PLUS_RELATIONS
|
||||
) {
|
||||
entities {
|
||||
id
|
||||
account_id
|
||||
total_debits
|
||||
void
|
||||
remaining_due
|
||||
date
|
||||
due_date
|
||||
end_date
|
||||
delinquent
|
||||
debits {
|
||||
entities {
|
||||
id
|
||||
quantity
|
||||
service_id
|
||||
service_name
|
||||
amount
|
||||
}
|
||||
}
|
||||
credits {
|
||||
entities {
|
||||
amount
|
||||
}
|
||||
}
|
||||
}
|
||||
page_info {
|
||||
page
|
||||
records_per_page
|
||||
total_count
|
||||
total_pages
|
||||
}
|
||||
}
|
||||
}',
|
||||
'variables' => [
|
||||
'paginator' => [
|
||||
'page' => $page,
|
||||
'records_per_page' => $limit
|
||||
],
|
||||
'search' => [],
|
||||
'sorter' => [
|
||||
[
|
||||
'attribute' => 'updated_at',
|
||||
'direction' => 'ASC',
|
||||
]
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$response = $this->client->createRequest()
|
||||
->setMethod('POST')
|
||||
->setData($data)
|
||||
->send();
|
||||
|
||||
$invoice = json_decode($response->getContent(), true);
|
||||
|
||||
return $invoice['form_params']['data']['invoices']['entities'][0];
|
||||
}
|
||||
|
||||
public function storeInvoices($invoices)
|
||||
{
|
||||
foreach ($invoices as $invoice) {
|
||||
$this->storeInvoice($invoice);
|
||||
}
|
||||
}
|
||||
|
||||
public function storeInvoice($invoice)
|
||||
{
|
||||
\Yii::debug($invoice);
|
||||
// $remainingDue is the Entire Invoice remaining to be paid amount, 0 = everything paid
|
||||
$remainingDue = $invoice['remaining_due'];
|
||||
// debits = charges on the account
|
||||
// credits = payments on the account
|
||||
|
||||
foreach ($invoice['debits']['entities'] as $i => $rawItem) {
|
||||
$invoiceItem = InvoiceItem::find()->where(['sonar_id' => (int)$rawItem['id']])->one();
|
||||
if (null === $invoiceItem) { // create new invoice item
|
||||
|
||||
$account = Account::findOne(['sonar_id' => (int)$invoice['account_id']]);
|
||||
$service = Service::findOne(['sonar_id' => (int)$rawItem['service_id']]);
|
||||
\Yii::debug($rawItem);
|
||||
if ($service && $account) {
|
||||
\Yii::debug($invoice);
|
||||
$payment = (isset($invoice['credits']['entities'][$i]['amount'])) ? $invoice['credits']['entities'][$i]['amount'] : 0;
|
||||
// @todo check payment - i think it is wrong to assume we have the same credits and debits ^ CGS
|
||||
$invoiceItem = new InvoiceItem([
|
||||
'sonar_id' => (int)$rawItem['id'],
|
||||
'account_id' => $account->id,
|
||||
'service_id' => $service->id,
|
||||
'name' => $rawItem['service_name'],
|
||||
'status' => InvoiceItem::STATUS_OPEN,
|
||||
'charge' => $rawItem['amount'],
|
||||
'payment' => $payment,
|
||||
'is_commissionable' => $service->hasCommission(),
|
||||
]);
|
||||
$invoiceItem->save();
|
||||
}
|
||||
}
|
||||
|
||||
// is the invoice item paid?
|
||||
if ($invoiceItem && $remainingDue == 0) {
|
||||
$invoiceItem->status = InvoiceItem::STATUS_PAYMENT_RECEIVED;
|
||||
$invoiceItem->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function mapAccounts($accounts)
|
||||
{
|
||||
$mapped = [];
|
||||
$i = 0;
|
||||
$db = \Yii::$app->db;
|
||||
foreach ($accounts as $account) {
|
||||
$mapped[$i]['sonar_id'] = (int)$account['id'];
|
||||
$mapped[$i]['name'] = $account['name'];
|
||||
|
||||
/**
|
||||
* [
|
||||
* 'id' => '132'
|
||||
* 'quantity' => 1
|
||||
* 'name_override' => 'Bradley'
|
||||
* 'price_override' => 0
|
||||
* 'price_override_reason' => 'testing'
|
||||
* 'service' => [
|
||||
* 'id' => '10'
|
||||
* 'name' => 'Business Giga Speed Internet'
|
||||
* 'amount' => 18000
|
||||
* 'enabled' => true
|
||||
* 'application' => 'DEBIT'
|
||||
* 'type' => 'DATA'
|
||||
* ]
|
||||
* ]
|
||||
*/
|
||||
$mapped[$i]['services'] = []; // init empty array
|
||||
|
||||
foreach ($account['account_services']['entities'] as $key => $account_service) {
|
||||
$mapped[$i]['services'][$key]['sonar_id'] = (int)$account_service['service']['id'];
|
||||
$mapped[$i]['services'][$key]['name'] = (!empty($account_service['name_override'])) ? $account_service['name_override'] : $account_service['service']['name'];
|
||||
$mapped[$i]['services'][$key]['price'] = (!empty($account_service['price_override'])) ? $account_service['price_override'] : $account_service['service']['amount'];
|
||||
if ($account_service['service']['application'] === 'CREDIT') {
|
||||
$mapped[$i]['services'][$key]['price'] = -1 * $mapped[$i]['services'][$key]['price'];// store as a negative
|
||||
}
|
||||
|
||||
// set to 0 if null after credit
|
||||
if (null === $mapped[$i]['services'][$key]['price']) {
|
||||
$mapped[$i]['services'][$key]['price'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$name = $account['custom_field_data']['entities'][0]['value'];
|
||||
$salesAgent = SalesAgent::findOne(['name' => $name]);
|
||||
if (null === $salesAgent) {
|
||||
$salesAgent = new SalesAgent(['name' => $name]);
|
||||
$salesAgent->save();
|
||||
}
|
||||
|
||||
$mapped[$i]['sales_agent_id'] = $salesAgent->id;
|
||||
|
||||
$i++;
|
||||
}
|
||||
return $mapped;
|
||||
}
|
||||
|
||||
public function storeAccounts()
|
||||
{
|
||||
$page = 1;
|
||||
do {
|
||||
$batch = $this->getAccounts($page, 100);
|
||||
$accounts = $this->mapAccounts($batch['accounts']['entities']);
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
$accountModel = Account::findOne(['sonar_id' => $account['sonar_id']]);
|
||||
if (null === $accountModel) {
|
||||
$accountModel = new Account([
|
||||
'sonar_id' => $account['sonar_id'],
|
||||
'name' => $account['name'],
|
||||
'sales_agent_id' => $account['sales_agent_id'],
|
||||
]);
|
||||
$accountModel->save();
|
||||
} else {
|
||||
//$accountModel->sonar_id = $account['sonar_id'];
|
||||
$accountModel->name = $account['name'];
|
||||
$accountModel->sales_agent_id = $account['sales_agent_id'];
|
||||
$accountModel->save();
|
||||
}
|
||||
|
||||
foreach ($account['services'] as $rawServiceData) {
|
||||
$serviceModel = Service::findOne(['sonar_id' => (int)$rawServiceData['sonar_id']]);
|
||||
if (null === $serviceModel) {
|
||||
$serviceModel = new Service([
|
||||
'sonar_id' => $rawServiceData['sonar_id'],
|
||||
'name' => $rawServiceData['name'],
|
||||
'price' => $rawServiceData['price'],
|
||||
'account_id' => $accountModel->id,
|
||||
'active' => 1, // @todo pull active state in from sonar api
|
||||
]);
|
||||
$serviceModel->save();
|
||||
} else {
|
||||
$serviceModel->commission = $serviceModel->getFormattedDollar($serviceModel->commission, false);
|
||||
$serviceModel->sonar_id = $rawServiceData['sonar_id'];
|
||||
$serviceModel->name = $rawServiceData['name'];
|
||||
$serviceModel->price = $rawServiceData['price'];
|
||||
$serviceModel->account_id = $accountModel->id;
|
||||
if (!empty($serviceModel->dirtyAttributes)) {
|
||||
if (isset($serviceModel->dirtyAttributes['price'])) {
|
||||
//Yii::$app->queue->push(new EmailJob([
|
||||
// 'templateAlias' => EmailJob::PRICE_CHANGE,
|
||||
// "email" => Yii::$app->params['adminEmail'],
|
||||
// 'templateModel' => [
|
||||
// "action_edit_url" => Yii::$app->urlManager->createAbsoluteUrl(
|
||||
// ['service/update', 'id' => $serviceModel->id]
|
||||
// ),
|
||||
// ]
|
||||
//]));
|
||||
}
|
||||
}
|
||||
$serviceModel->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$page++;
|
||||
} while ($page < ($batch['accounts']['page_info']['total_pages'] + 1));
|
||||
}
|
||||
|
||||
public function processInvoices(int $invoiceId)
|
||||
{
|
||||
dump($this->getInvoice($invoiceId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,12 +19,12 @@ class Yii {
|
||||
}
|
||||
|
||||
/**
|
||||
* @property yii\rbac\DbManager $authManager
|
||||
* @property \Da\User\Model\User $user
|
||||
* @property \common\components\SonarApiComponent $sonar
|
||||
* @property \common\components\HubspotApiComponent $hubspot
|
||||
* @property \common\components\PostmarkComponent $postmark
|
||||
* @property \yii\queue\db\Queue $queue
|
||||
* @property yii\rbac\DbManager $authManager
|
||||
* @property \Da\User\Model\User $user
|
||||
* @property \common\components\GeminiApiComponent $sonar
|
||||
* @property \common\components\HubspotApiComponent $hubspot
|
||||
* @property \common\components\PostmarkComponent $postmark
|
||||
* @property \yii\queue\db\Queue $queue
|
||||
*
|
||||
*/
|
||||
class __Application {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
use common\components\PostmarkComponent;
|
||||
use common\components\SonarApiComponent;
|
||||
use common\components\GeminiApiComponent;
|
||||
use common\components\HubspotApiComponent;
|
||||
use yii\caching\FileCache;
|
||||
use yii\queue\db\Queue;
|
||||
@@ -22,10 +22,11 @@ return [
|
||||
'cache' => [
|
||||
'class' => FileCache::class,
|
||||
],
|
||||
'sonar' => [
|
||||
'class' => SonarApiComponent::class,
|
||||
'baseUrl' => $params['sonar.url'] . '/api/graphql',
|
||||
'bearerToken' => $params['sonar.bearerToken'],
|
||||
'gemini' => [
|
||||
'class' => GeminiApiComponent::class,
|
||||
'baseUrl' => $params['gemini.url'],
|
||||
'apiKey' => $params['gemini.key'],
|
||||
'model' => $params['gemini.model'],
|
||||
],
|
||||
'postmark' => [
|
||||
'class' => PostmarkComponent::class,
|
||||
|
||||
@@ -6,8 +6,9 @@ return [
|
||||
'senderName' => 'Example.com mailer',
|
||||
'user.passwordResetTokenExpire' => 3600,
|
||||
'user.passwordMinLength' => 8,
|
||||
'sonar.url' => 'https://yourname.sonar.software',
|
||||
'sonar.bearerToken' => '',
|
||||
'gemini.url' => 'https://generativelanguage.googleapis.com/v1beta/models',
|
||||
'gemini.model' => 'gemini-1.5-flash-8b:generateContent',
|
||||
'gemini.key' => '',
|
||||
'postmark.serverToken' => 'postmark-server-key',
|
||||
'postmark.messageStream' => 'outbound',
|
||||
'sentry.dsn' => 'https://asdf@o4507934844780544.ingest.us.sentry.io/4508006893158400',
|
||||
|
||||
@@ -32,10 +32,10 @@ class EmailJob extends BaseObject implements RetryableJobInterface
|
||||
$this->templateModel = array_merge($this->templateModel, [
|
||||
"product" => Yii::$app->params['product_name'],
|
||||
"product_name" => Yii::$app->params['product_name'],
|
||||
"support_url" => Yii::$app->params['support_url'],
|
||||
//"support_url" => Yii::$app->params['support_url'],
|
||||
"product_url" => Yii::$app->urlManager->createAbsoluteUrl(['site/index']),
|
||||
"company_name" => Yii::$app->params['company_name'],
|
||||
"company_address" => Yii::$app->params['company_address'],
|
||||
//"company_address" => Yii::$app->params['company_address'],
|
||||
]);
|
||||
|
||||
Yii::$app->postmark->client->sendEmailWithTemplate(
|
||||
|
||||
@@ -7,18 +7,22 @@ namespace common\models;
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $file_name
|
||||
* @property string $food_name
|
||||
* @property int $calories
|
||||
* @property int $protein
|
||||
* @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
|
||||
{
|
||||
|
||||
public $base64File;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -33,8 +37,8 @@ class Meal extends \yii\db\ActiveRecord
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['file_name', 'calories', 'protein', 'fat', 'carbohydrates', 'fiber', 'meal', 'created_at', 'updated_at'], 'required'],
|
||||
[['calories', 'protein', 'fat', 'carbohydrates', 'fiber', 'meal', 'created_at', 'updated_at'], 'integer'],
|
||||
[['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'],
|
||||
[['file_name'], 'string', 'max' => 255],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -54,26 +54,24 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
];
|
||||
|
||||
// register event
|
||||
$this->on(self::EVENT_AFTER_INSERT, [$this, 'emailTrigger']);
|
||||
$this->on(self::EVENT_AFTER_UPDATE, [$this, 'emailTrigger']);
|
||||
//$this->on(self::EVENT_AFTER_INSERT, [$this, 'emailTrigger']);
|
||||
//$this->on(self::EVENT_AFTER_UPDATE, [$this, 'emailTrigger']);
|
||||
}
|
||||
|
||||
|
||||
public function emailTrigger(AfterSaveEvent $event)
|
||||
{
|
||||
if ($event->sender->status == self::STATUS_ACTIVE && !$event->sender->welcome_email_sent) {
|
||||
Yii::$app->queue->push(new EmailJob([
|
||||
'templateAlias' => EmailJob::WELCOME_EMAIL,
|
||||
'email' => $event->sender->email,
|
||||
'templateModel' => [
|
||||
"name" => $event->sender->first_name,
|
||||
"action_url" => Yii::$app->urlManager->createAbsoluteUrl(['site/login']),
|
||||
]
|
||||
]));
|
||||
Yii::$app->queue->push(new EmailJob([
|
||||
'templateAlias' => EmailJob::WELCOME_EMAIL,
|
||||
'email' => $event->sender->email,
|
||||
'templateModel' => [
|
||||
"name" => $event->sender->first_name,
|
||||
"action_url" => Yii::$app->urlManager->createAbsoluteUrl(['site/login']),
|
||||
]
|
||||
]));
|
||||
|
||||
$event->sender->welcome_email_sent = true;
|
||||
$event->sender->save(false);
|
||||
}
|
||||
$event->sender->welcome_email_sent = true;
|
||||
$event->sender->save(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +89,7 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['status', 'default', 'value' => self::STATUS_UNVERIFIED],
|
||||
['status', 'default', 'value' => self::STATUS_VERIFIED],
|
||||
[['email'], 'email'],
|
||||
[['email'], 'unique'],
|
||||
[['sales_agent_id', 'created_at', 'updated_at'], 'integer'],
|
||||
|
||||
@@ -3,20 +3,17 @@
|
||||
"require": {
|
||||
"php": ">=7.4.0",
|
||||
"ext-json": "*",
|
||||
"yiisoft/yii2": "~2.0.45",
|
||||
"yiisoft/yii2-bootstrap5": "@dev",
|
||||
"yiisoft/yii2-authclient": "^2.2",
|
||||
"yiisoft/yii2-httpclient": "~2.0",
|
||||
"cgsmith/yii2-flatpickr-widget": "~1.1",
|
||||
"yiisoft/yii2-queue": "^2.3",
|
||||
"wildbit/postmark-php": "^6.0",
|
||||
"donatj/phpuseragentparser": "^1.9",
|
||||
"twbs/bootstrap-icons": "^1.11",
|
||||
"ramsey/uuid": "^4.7",
|
||||
"sentry/sentry": "^4.9",
|
||||
"kartik-v/yii2-widget-select2": "^2.2",
|
||||
"kartik-v/yii2-grid": "dev-master",
|
||||
"kartik-v/yii2-editable": "^1.8",
|
||||
"kartik-v/yii2-icons": "^1.4"
|
||||
"twbs/bootstrap-icons": "^1.11",
|
||||
"wildbit/postmark-php": "^6.0",
|
||||
"yiisoft/yii2": "~2.0.45",
|
||||
"yiisoft/yii2-authclient": "^2.2",
|
||||
"yiisoft/yii2-bootstrap5": "@dev",
|
||||
"yiisoft/yii2-httpclient": "~2.0",
|
||||
"yiisoft/yii2-queue": "^2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "^5.1",
|
||||
@@ -36,6 +33,7 @@
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"php-http/discovery": true,
|
||||
"yiisoft/yii2-composer": true
|
||||
},
|
||||
"process-timeout": 1800,
|
||||
@@ -52,6 +50,10 @@
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "https://asset-packagist.org"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "git@github.com:eficiencia-fiscal/gemini-client.git"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
908
composer.lock
generated
908
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c38ad4634c62615dbe2a183401f93003",
|
||||
"content-hash": "2aa71ca3104de10ae9406cd03e93cd1d",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bower-asset/bootstrap",
|
||||
@@ -60,27 +60,6 @@
|
||||
"MIT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bower-asset/jquery-ui",
|
||||
"version": "1.12.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:components/jqueryui.git",
|
||||
"reference": "44ecf3794cc56b65954cc19737234a3119d036cc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/components/jqueryui/zipball/44ecf3794cc56b65954cc19737234a3119d036cc",
|
||||
"reference": "44ecf3794cc56b65954cc19737234a3119d036cc"
|
||||
},
|
||||
"require": {
|
||||
"bower-asset/jquery": ">=1.6"
|
||||
},
|
||||
"type": "bower-asset",
|
||||
"license": [
|
||||
"MIT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bower-asset/punycode",
|
||||
"version": "v1.4.1",
|
||||
@@ -117,6 +96,66 @@
|
||||
"MIT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.12.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/brick/math.git",
|
||||
"reference": "f510c0a40911935b77b86859eb5223d58d660df1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1",
|
||||
"reference": "f510c0a40911935b77b86859eb5223d58d660df1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^2.2",
|
||||
"phpunit/phpunit": "^10.1",
|
||||
"vimeo/psalm": "5.16.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Arbitrary-precision arithmetic library",
|
||||
"keywords": [
|
||||
"Arbitrary-precision",
|
||||
"BigInteger",
|
||||
"BigRational",
|
||||
"arithmetic",
|
||||
"bigdecimal",
|
||||
"bignum",
|
||||
"bignumber",
|
||||
"brick",
|
||||
"decimal",
|
||||
"integer",
|
||||
"math",
|
||||
"mathematics",
|
||||
"rational"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/brick/math/issues",
|
||||
"source": "https://github.com/brick/math/tree/0.12.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/BenMorel",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-29T23:19:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "cebe/markdown",
|
||||
"version": "1.2.1",
|
||||
@@ -238,47 +277,6 @@
|
||||
},
|
||||
"time": "2024-09-25T08:16:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "components/flag-icon-css",
|
||||
"version": "v7.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lipis/flag-icons.git",
|
||||
"reference": "fe15c16e7463d0c66d6c5730e9d0e832438d98e1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lipis/flag-icons/zipball/fe15c16e7463d0c66d6c5730e9d0e832438d98e1",
|
||||
"reference": "fe15c16e7463d0c66d6c5730e9d0e832438d98e1",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Panayiotis Lipiridis",
|
||||
"email": "lipiridis@gmail.com",
|
||||
"role": "Lead"
|
||||
}
|
||||
],
|
||||
"description": "A curated collection of all country flags in SVG — plus the CSS for easier integration.",
|
||||
"homepage": "https://flagicons.lipis.dev",
|
||||
"keywords": [
|
||||
"country",
|
||||
"country-flags",
|
||||
"css",
|
||||
"icon-css",
|
||||
"svg"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/lipis/flag-icons/issues",
|
||||
"source": "https://github.com/lipis/flag-icons/tree/v7.3.2"
|
||||
},
|
||||
"time": "2025-01-17T14:03:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "donatj/phpuseragentparser",
|
||||
"version": "v1.10.0",
|
||||
@@ -798,539 +796,6 @@
|
||||
},
|
||||
"time": "2024-11-18T16:19:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/bootstrap-popover-x",
|
||||
"version": "v1.5.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/bootstrap-popover-x.git",
|
||||
"reference": "879def62529797833e10885b6e77864e83e9e240"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/bootstrap-popover-x/zipball/879def62529797833e10885b6e77864e83e9e240",
|
||||
"reference": "879def62529797833e10885b6e77864e83e9e240",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.5.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\plugins\\popover\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://www.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "Bootstrap Popover Extended - Popover with modal behavior, styling enhancements and more.",
|
||||
"homepage": "https://github.com/kartik-v/bootstrap-popover-x",
|
||||
"keywords": [
|
||||
"bootstrap",
|
||||
"extended",
|
||||
"jquery",
|
||||
"modal",
|
||||
"modal-popover",
|
||||
"popover",
|
||||
"popover-x"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/bootstrap-popover-x/issues",
|
||||
"source": "https://github.com/kartik-v/bootstrap-popover-x/tree/v1.5.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/bootstrap-popover-x",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-12T13:23:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/yii2-dialog",
|
||||
"version": "v1.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/yii2-dialog.git",
|
||||
"reference": "510c3a35ffe79987cde9a9366cedbff545fd92d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/yii2-dialog/zipball/510c3a35ffe79987cde9a9366cedbff545fd92d4",
|
||||
"reference": "510c3a35ffe79987cde9a9366cedbff545fd92d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"kartik-v/yii2-krajee-base": ">=3.0.0"
|
||||
},
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\dialog\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://www.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "An asset bundle for bootstrap3-dialog for Yii 2.0 framework.",
|
||||
"homepage": "https://github.com/kartik-v/yii2-dialog",
|
||||
"keywords": [
|
||||
"alert",
|
||||
"bootstrap",
|
||||
"dialog",
|
||||
"extension",
|
||||
"modal",
|
||||
"yii2"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/yii2-dialog/issues",
|
||||
"source": "https://github.com/kartik-v/yii2-dialog/tree/v1.0.6"
|
||||
},
|
||||
"time": "2021-09-02T08:26:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/yii2-editable",
|
||||
"version": "v1.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/yii2-editable.git",
|
||||
"reference": "ae4cc2384e667ba9dfe8bfb0098716caeb2500a8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/yii2-editable/zipball/ae4cc2384e667ba9dfe8bfb0098716caeb2500a8",
|
||||
"reference": "ae4cc2384e667ba9dfe8bfb0098716caeb2500a8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"kartik-v/yii2-popover-x": "~1.3",
|
||||
"kartik-v/yii2-widget-activeform": ">=1.6.2"
|
||||
},
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\editable\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://www.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "An enhanced editable widget for Yii 2.0 that allows easy editing of displayed data with numerous configuration possibilities.",
|
||||
"homepage": "https://github.com/kartik-v/yii2-editable",
|
||||
"keywords": [
|
||||
"bootstrap",
|
||||
"editable",
|
||||
"input",
|
||||
"jquery",
|
||||
"popover",
|
||||
"popover-x",
|
||||
"widget"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/yii2-editable/issues",
|
||||
"source": "https://github.com/kartik-v/yii2-editable/tree/v1.8.0"
|
||||
},
|
||||
"time": "2022-04-29T12:51:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/yii2-grid",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/yii2-grid.git",
|
||||
"reference": "bcaacfc442b8c7ac97c00c52dfdb5f7ebdca4e0c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/yii2-grid/zipball/bcaacfc442b8c7ac97c00c52dfdb5f7ebdca4e0c",
|
||||
"reference": "bcaacfc442b8c7ac97c00c52dfdb5f7ebdca4e0c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"kartik-v/yii2-dialog": "~1.0",
|
||||
"kartik-v/yii2-krajee-base": ">=3.0.3"
|
||||
},
|
||||
"suggest": {
|
||||
"kartik-v/yii2-bootstrap4-dropdown": "For enabling dropdown support when using with Bootstrap v4.x",
|
||||
"kartik-v/yii2-bootstrap5-dropdown": "For enabling dropdown support when using with Bootstrap v5.x",
|
||||
"kartik-v/yii2-mpdf": "For exporting grids to PDF"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.5.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\grid\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://www.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "Yii 2 GridView on steroids. Various enhancements and utilities for the Yii 2.0 GridView widget.",
|
||||
"homepage": "https://github.com/kartik-v/yii2-grid",
|
||||
"keywords": [
|
||||
"extension",
|
||||
"grid",
|
||||
"widget",
|
||||
"yii2"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/yii2-grid/issues",
|
||||
"source": "https://github.com/kartik-v/yii2-grid/tree/master"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/yii2-grid",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2023-10-15T08:11:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/yii2-icons",
|
||||
"version": "v1.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/yii2-icons.git",
|
||||
"reference": "81334b3d888d4baaeb6ac458475258130474237e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/yii2-icons/zipball/81334b3d888d4baaeb6ac458475258130474237e",
|
||||
"reference": "81334b3d888d4baaeb6ac458475258130474237e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"components/flag-icon-css": "*",
|
||||
"kartik-v/yii2-krajee-base": ">=3.0.4",
|
||||
"yiisoft/yii2-jui": "*"
|
||||
},
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\icons\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://demos.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "Set of icon frameworks for use in Yii Framework 2.0",
|
||||
"homepage": "https://github.com/kartik-v/yii2-icons",
|
||||
"keywords": [
|
||||
"extension",
|
||||
"font",
|
||||
"icon",
|
||||
"yii",
|
||||
"yii2"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/yii2-icons/issues",
|
||||
"source": "https://github.com/kartik-v/yii2-icons/tree/v1.4.8"
|
||||
},
|
||||
"time": "2022-03-04T10:34:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/yii2-krajee-base",
|
||||
"version": "v3.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/yii2-krajee-base.git",
|
||||
"reference": "5c095126d1be47e0bb1f92779b7dc099f6feae31"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/yii2-krajee-base/zipball/5c095126d1be47e0bb1f92779b7dc099f6feae31",
|
||||
"reference": "5c095126d1be47e0bb1f92779b7dc099f6feae31",
|
||||
"shasum": ""
|
||||
},
|
||||
"suggest": {
|
||||
"yiisoft/yii2-bootstrap": "for Krajee extensions to work with Bootstrap 3.x version",
|
||||
"yiisoft/yii2-bootstrap4": "for Krajee extensions to work with Bootstrap 4.x version",
|
||||
"yiisoft/yii2-bootstrap5": "for Krajee extensions to work with Bootstrap 5.x version"
|
||||
},
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\base\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://www.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "Base library and foundation components for all Yii2 Krajee extensions.",
|
||||
"homepage": "https://github.com/kartik-v/yii2-krajee-base",
|
||||
"keywords": [
|
||||
"base",
|
||||
"extension",
|
||||
"foundation",
|
||||
"krajee",
|
||||
"widget",
|
||||
"yii2"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/yii2-krajee-base/issues",
|
||||
"source": "https://github.com/kartik-v/yii2-krajee-base/tree/v3.0.5"
|
||||
},
|
||||
"time": "2022-06-01T14:05:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/yii2-popover-x",
|
||||
"version": "v1.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/yii2-popover-x.git",
|
||||
"reference": "b0320d1315bbfce31ec8907882c6f4abed223a28"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/yii2-popover-x/zipball/b0320d1315bbfce31ec8907882c6f4abed223a28",
|
||||
"reference": "b0320d1315bbfce31ec8907882c6f4abed223a28",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"kartik-v/bootstrap-popover-x": ">=1.4",
|
||||
"kartik-v/yii2-krajee-base": ">=2.0"
|
||||
},
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\popover\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://www.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "An extended bootstrap 3.0 popover widget which combines both the bootstrap popover and modal features and includes various new styling enhancements.",
|
||||
"homepage": "https://github.com/kartik-v/yii2-popover-x",
|
||||
"keywords": [
|
||||
"bootstrap",
|
||||
"extended",
|
||||
"jquery",
|
||||
"modal",
|
||||
"modal-popover",
|
||||
"popover",
|
||||
"popover-x"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/yii2-popover-x/issues",
|
||||
"source": "https://github.com/kartik-v/yii2-popover-x/tree/master"
|
||||
},
|
||||
"time": "2020-04-02T17:20:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/yii2-widget-activeform",
|
||||
"version": "v1.6.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/yii2-widget-activeform.git",
|
||||
"reference": "697407c8fa9c81593a7bb9bef4b7ad53f7d38b79"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/yii2-widget-activeform/zipball/697407c8fa9c81593a7bb9bef4b7ad53f7d38b79",
|
||||
"reference": "697407c8fa9c81593a7bb9bef4b7ad53f7d38b79",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"kartik-v/yii2-krajee-base": ">=3.0.3"
|
||||
},
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.6.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\form\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://www.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "Enhanced Yii2 active-form and active-field with full bootstrap styling support (sub repo split from yii2-widgets).",
|
||||
"homepage": "https://github.com/kartik-v/yii2-widget-activeform",
|
||||
"keywords": [
|
||||
"activefield",
|
||||
"activeform",
|
||||
"extension",
|
||||
"field",
|
||||
"form",
|
||||
"widget",
|
||||
"yii2"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/yii2-widget-activeform/issues",
|
||||
"source": "https://github.com/kartik-v/yii2-widget-activeform/tree/v1.6.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/yii2-widgets",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-31T11:33:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kartik-v/yii2-widget-select2",
|
||||
"version": "v2.2.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kartik-v/yii2-widget-select2.git",
|
||||
"reference": "4b8ef7dd9780531fc997fa23a53a38a1f7674bec"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kartik-v/yii2-widget-select2/zipball/4b8ef7dd9780531fc997fa23a53a38a1f7674bec",
|
||||
"reference": "4b8ef7dd9780531fc997fa23a53a38a1f7674bec",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"kartik-v/yii2-krajee-base": ">=3.0.4",
|
||||
"select2/select2": ">=4.0.0"
|
||||
},
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"kartik\\select2\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kartik Visweswaran",
|
||||
"email": "kartikv2@gmail.com",
|
||||
"homepage": "http://www.krajee.com/"
|
||||
}
|
||||
],
|
||||
"description": "Enhanced Yii2 wrapper for the Select2 jQuery plugin (sub repo split from yii2-widgets).",
|
||||
"homepage": "https://github.com/kartik-v/yii2-widget-select2",
|
||||
"keywords": [
|
||||
"dropdown",
|
||||
"extension",
|
||||
"form",
|
||||
"jquery",
|
||||
"plugin",
|
||||
"select2",
|
||||
"widget",
|
||||
"yii2"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/kartik-v/yii2-widget-select2/issues",
|
||||
"source": "https://github.com/kartik-v/yii2-widget-select2/tree/v2.2.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/yii2-widget-select2",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2023-06-22T07:43:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "npm-asset/flatpickr",
|
||||
"version": "4.6.13",
|
||||
@@ -1648,46 +1113,185 @@
|
||||
"time": "2019-03-08T08:55:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "select2/select2",
|
||||
"version": "4.0.13",
|
||||
"name": "ramsey/collection",
|
||||
"version": "2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/select2/select2.git",
|
||||
"reference": "45f2b83ceed5231afa7b3d5b12b58ad335edd82e"
|
||||
"url": "https://github.com/ramsey/collection.git",
|
||||
"reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/select2/select2/zipball/45f2b83ceed5231afa7b3d5b12b58ad335edd82e",
|
||||
"reference": "45f2b83ceed5231afa7b3d5b12b58ad335edd82e",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5",
|
||||
"reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "component",
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"captainhook/plugin-composer": "^5.3",
|
||||
"ergebnis/composer-normalize": "^2.28.3",
|
||||
"fakerphp/faker": "^1.21",
|
||||
"hamcrest/hamcrest-php": "^2.0",
|
||||
"jangregor/phpstan-prophecy": "^1.0",
|
||||
"mockery/mockery": "^1.5",
|
||||
"php-parallel-lint/php-console-highlighter": "^1.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3",
|
||||
"phpcsstandards/phpcsutils": "^1.0.0-rc1",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpstan/extension-installer": "^1.2",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpstan/phpstan-mockery": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.3",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psalm/plugin-mockery": "^1.1",
|
||||
"psalm/plugin-phpunit": "^0.18.4",
|
||||
"ramsey/coding-standard": "^2.0.3",
|
||||
"ramsey/conventional-commits": "^1.3",
|
||||
"vimeo/psalm": "^5.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"component": {
|
||||
"files": [
|
||||
"dist/js/select2.js",
|
||||
"dist/js/i18n/*.js",
|
||||
"dist/css/select2.css"
|
||||
],
|
||||
"styles": [
|
||||
"dist/css/select2.css"
|
||||
],
|
||||
"scripts": [
|
||||
"dist/js/select2.js"
|
||||
]
|
||||
"captainhook": {
|
||||
"force-install": true
|
||||
},
|
||||
"ramsey/conventional-commits": {
|
||||
"configFile": "conventional-commits.json"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Collection\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Select2 is a jQuery based replacement for select boxes.",
|
||||
"homepage": "https://select2.org/",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Ramsey",
|
||||
"email": "ben@benramsey.com",
|
||||
"homepage": "https://benramsey.com"
|
||||
}
|
||||
],
|
||||
"description": "A PHP library for representing and manipulating collections.",
|
||||
"keywords": [
|
||||
"array",
|
||||
"collection",
|
||||
"hash",
|
||||
"map",
|
||||
"queue",
|
||||
"set"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/select2/select2/issues",
|
||||
"source": "https://github.com/select2/select2/tree/4.0.13"
|
||||
"issues": "https://github.com/ramsey/collection/issues",
|
||||
"source": "https://github.com/ramsey/collection/tree/2.0.0"
|
||||
},
|
||||
"time": "2020-01-28T05:01:22+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ramsey",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-12-31T21:50:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "4.7.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "91039bc1faa45ba123c4328958e620d382ec7088"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
|
||||
"reference": "91039bc1faa45ba123c4328958e620d382ec7088",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
|
||||
"ext-json": "*",
|
||||
"php": "^8.0",
|
||||
"ramsey/collection": "^1.2 || ^2.0"
|
||||
},
|
||||
"replace": {
|
||||
"rhumsaa/uuid": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"captainhook/captainhook": "^5.10",
|
||||
"captainhook/plugin-composer": "^5.3",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
||||
"doctrine/annotations": "^1.8",
|
||||
"ergebnis/composer-normalize": "^2.15",
|
||||
"mockery/mockery": "^1.3",
|
||||
"paragonie/random-lib": "^2",
|
||||
"php-mock/php-mock": "^2.2",
|
||||
"php-mock/php-mock-mockery": "^1.3",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.1",
|
||||
"phpbench/phpbench": "^1.0",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpstan/phpstan-mockery": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.1",
|
||||
"phpunit/phpunit": "^8.5 || ^9",
|
||||
"ramsey/composer-repl": "^1.4",
|
||||
"slevomat/coding-standard": "^8.4",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.9"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
||||
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
|
||||
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
|
||||
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
||||
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"captainhook": {
|
||||
"force-install": true
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Ramsey\\Uuid\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
|
||||
"keywords": [
|
||||
"guid",
|
||||
"identifier",
|
||||
"uuid"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/uuid/issues",
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.7.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ramsey",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-27T21:32:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sentry/sentry",
|
||||
@@ -2507,59 +2111,6 @@
|
||||
],
|
||||
"time": "2025-02-13T21:09:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "yiisoft/yii2-jui",
|
||||
"version": "2.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/yiisoft/yii2-jui.git",
|
||||
"reference": "ce45c16d4fbbe7d1c516d8d0e8311e07f6138eed"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/yiisoft/yii2-jui/zipball/ce45c16d4fbbe7d1c516d8d0e8311e07f6138eed",
|
||||
"reference": "ce45c16d4fbbe7d1c516d8d0e8311e07f6138eed",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"bower-asset/jquery-ui": "~1.12.1",
|
||||
"yiisoft/yii2": "~2.0.4"
|
||||
},
|
||||
"type": "yii2-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"yii\\jui\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Qiang Xue",
|
||||
"email": "qiang.xue@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "The Jquery UI extension for the Yii framework",
|
||||
"keywords": [
|
||||
"jQuery UI",
|
||||
"yii2"
|
||||
],
|
||||
"support": {
|
||||
"forum": "http://www.yiiframework.com/forum/",
|
||||
"irc": "irc://irc.freenode.net/yii",
|
||||
"issues": "https://github.com/yiisoft/yii2-jui/issues",
|
||||
"source": "https://github.com/yiisoft/yii2-jui",
|
||||
"wiki": "http://www.yiiframework.com/wiki/"
|
||||
},
|
||||
"time": "2017-11-25T15:32:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "yiisoft/yii2-queue",
|
||||
"version": "2.3.7",
|
||||
@@ -3337,16 +2888,16 @@
|
||||
},
|
||||
{
|
||||
"name": "deployer/deployer",
|
||||
"version": "v7.5.11",
|
||||
"version": "v7.5.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/deployphp/deployer.git",
|
||||
"reference": "448761221383877d61bed6700805001f872c0ad3"
|
||||
"reference": "efc71dac9ccc86b3f9946e75d50cb106b775aae2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/deployphp/deployer/zipball/448761221383877d61bed6700805001f872c0ad3",
|
||||
"reference": "448761221383877d61bed6700805001f872c0ad3",
|
||||
"url": "https://api.github.com/repos/deployphp/deployer/zipball/efc71dac9ccc86b3f9946e75d50cb106b775aae2",
|
||||
"reference": "efc71dac9ccc86b3f9946e75d50cb106b775aae2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3387,7 +2938,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-10T14:27:00+00:00"
|
||||
"time": "2025-02-19T16:45:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
@@ -6903,7 +6454,6 @@
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"kartik-v/yii2-grid": 20,
|
||||
"yiisoft/yii2-bootstrap5": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
|
||||
@@ -15,12 +15,14 @@ class m250219_133939_create_meal_table extends Migration
|
||||
$this->createTable('{{%meal}}', [
|
||||
'id' => $this->primaryKey(),
|
||||
'file_name' => $this->string()->notNull(),
|
||||
'food_name' => $this->string()->notNull(),
|
||||
'calories' => $this->integer()->notNull(),
|
||||
'protein' => $this->integer()->notNull(),
|
||||
'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(),
|
||||
]);
|
||||
|
||||
@@ -15,7 +15,7 @@ class ConfettiAsset extends AssetBundle
|
||||
public $css = [
|
||||
];
|
||||
public $js = [
|
||||
'//cdn.jsdelivr.net/npm/canvas-confetti@1.5.1/dist/confetti.browser.min.js',
|
||||
'//cdn.jsdelivr.net/npm/canvas-confetti@1.9.3/dist/confetti.browser.min.js',
|
||||
];
|
||||
public $depends = [
|
||||
];
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
namespace frontend\controllers;
|
||||
|
||||
use common\models\Meal;
|
||||
use frontend\models\MealForm;
|
||||
use Yii;
|
||||
use yii\data\ActiveDataProvider;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\web\Controller;
|
||||
use yii\web\NotFoundHttpException;
|
||||
use yii\filters\VerbFilter;
|
||||
use yii\web\UploadedFile;
|
||||
|
||||
/**
|
||||
* MealController implements the CRUD actions for Meal model.
|
||||
@@ -21,8 +25,17 @@ class MealController extends Controller
|
||||
return array_merge(
|
||||
parent::behaviors(),
|
||||
[
|
||||
'access' => [
|
||||
'class' => AccessControl::class,
|
||||
'rules' => [
|
||||
[
|
||||
'allow' => true,
|
||||
'roles' => ['@'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::className(),
|
||||
'class' => VerbFilter::class,
|
||||
'actions' => [
|
||||
'delete' => ['POST'],
|
||||
],
|
||||
@@ -57,6 +70,28 @@ class MealController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function actionUpload()
|
||||
{
|
||||
$model = new MealForm();
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('upload', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
public function actionSuccess()
|
||||
{
|
||||
return $this->render('success');
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a single Meal model.
|
||||
* @param int $id ID
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace frontend\controllers;
|
||||
|
||||
use common\components\SonarApiComponent;
|
||||
use common\components\GeminiApiComponent;
|
||||
use common\jobs\EmailJob;
|
||||
use frontend\models\ResendVerificationEmailForm;
|
||||
use frontend\models\VerifyEmailForm;
|
||||
@@ -162,7 +162,7 @@ class SiteController extends Controller
|
||||
return Yii::$app->response->send();
|
||||
}
|
||||
|
||||
/** @var SonarApiComponent $api */
|
||||
/** @var GeminiApiComponent $api */
|
||||
$api = Yii::$app->sonar;
|
||||
$object = json_decode(Yii::$app->request->getRawBody());
|
||||
|
||||
|
||||
41
frontend/models/MealForm.php
Normal file
41
frontend/models/MealForm.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace frontend\models;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
use yii\web\UploadedFile;
|
||||
|
||||
class MealForm extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UploadedFile
|
||||
*/
|
||||
public $picture;
|
||||
public string $filepath;
|
||||
|
||||
public function rules() {
|
||||
return [
|
||||
[['picture'], 'file', 'skipOnEmpty' => false],
|
||||
[['picture'], 'required'],
|
||||
];
|
||||
}
|
||||
|
||||
public function newFileName()
|
||||
{
|
||||
$this->filepath = (string)'uploads/' . Yii::$app->user->id . '-' . Uuid::uuid4() . '.' . $this->picture->extension;
|
||||
}
|
||||
|
||||
public function upload()
|
||||
{
|
||||
if ($this->validate()) {
|
||||
$this->newFileName();
|
||||
$this->picture->saveAs($this->filepath);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,11 +69,19 @@ class SignupForm extends Model
|
||||
protected function sendEmail($user)
|
||||
{
|
||||
Yii::$app->queue->push(new EmailJob([
|
||||
'templateAlias' => EmailJob::VERIFY_EMAIL,
|
||||
'templateAlias' => EmailJob::ADMIN_NOTIFY,
|
||||
'email' => Yii::$app->params['supportEmail'],
|
||||
'templateModel' => [
|
||||
"name" => $user->first_name,
|
||||
"user_name" => $user->email,
|
||||
]
|
||||
]));
|
||||
Yii::$app->queue->push(new EmailJob([
|
||||
'templateAlias' => EmailJob::WELCOME_EMAIL,
|
||||
'email' => $user->email,
|
||||
'templateModel' => [
|
||||
"name" => $user->first_name,
|
||||
"action_url" => Yii::$app->urlManager->createAbsoluteUrl(['site/verify-email', 'token' => $user->verification_token]),
|
||||
"action_url" => Yii::$app->urlManager->createAbsoluteUrl(['site/login']),
|
||||
]
|
||||
]));
|
||||
|
||||
|
||||
@@ -45,7 +45,11 @@ $this->beginPage() ?>
|
||||
|
||||
if (!Yii::$app->user->isGuest) {
|
||||
$menuItems[] = [
|
||||
'label' => 'Meals',
|
||||
'label' => 'Capture Meal',
|
||||
'url' => [Url::to(['meal/upload'])],
|
||||
];
|
||||
$menuItems[] = [
|
||||
'label' => 'List Meals',
|
||||
'url' => [Url::to(['meal/index'])],
|
||||
];
|
||||
$menuItems[] = [
|
||||
|
||||
83
frontend/views/meal/success.php
Normal file
83
frontend/views/meal/success.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
use common\models\Meal;
|
||||
use frontend\assets\ConfettiAsset;
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
|
||||
$this->title = Yii::$app->name;
|
||||
|
||||
ConfettiAsset::register($this);
|
||||
|
||||
|
||||
$this->registerJs("
|
||||
var end = Date.now() + (2 * 1000);
|
||||
var scalar = 2;
|
||||
var foodEmojis = ['🍕', '🍔', '🍎', '🥑', '🥗', '🍣', '🍩', '🌮', '🍉', '🍞', '🍜', '🥩', '🍪', '🥕', '🧀', '🍓', '🍍', '🥒', '🍇', '🥞', '🦞', '🍗', '🍛'];
|
||||
// Create shapes from all emojis
|
||||
var emojiShapes = foodEmojis.map(emoji => confetti.shapeFromText({ text: emoji, scalar }));
|
||||
var colors = ['#4a8fc4', '#FFA500', '#585858'];
|
||||
// Function to pick 3 random unique emojis
|
||||
function getRandomEmojis() {
|
||||
let shuffled = emojiShapes.sort(() => 0.5 - Math.random());
|
||||
return shuffled.slice(0, 3); // Get first 3 elements
|
||||
}
|
||||
|
||||
// Detect if user is on a phone (simple check)
|
||||
var isMobile = window.innerWidth < 768; // Adjust as needed for tablets
|
||||
|
||||
(function frame() {
|
||||
confetti({
|
||||
particleCount: isMobile ? 1 : 2, // Fewer particles on mobile
|
||||
angle: 60,
|
||||
spread: isMobile ? 35 : 55, // Less spread on mobile,
|
||||
origin: { x: 0 },
|
||||
shapes: getRandomEmojis(),
|
||||
scalar: isMobile ? 1.5 : 2 // Slightly smaller on mobile
|
||||
});
|
||||
confetti({
|
||||
particleCount: isMobile ? 1 : 2, // Fewer particles on mobile
|
||||
angle: 120,
|
||||
spread: isMobile ? 35 : 55, // Less spread on mobile,
|
||||
origin: { x: 1 },
|
||||
shapes: getRandomEmojis(),
|
||||
scalar: isMobile ? 1.5 : 2 // Slightly smaller on mobile
|
||||
});
|
||||
|
||||
if (Date.now() < end) {
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
}());");
|
||||
?>
|
||||
<div class="analysis-result text-center p-4">
|
||||
<h2 class="mb-3">Yum! 🎉</h2>
|
||||
|
||||
<p class="lead">
|
||||
Our AI minions have <i>finished judging</i> you...
|
||||
and your food. But also you. 🤖🍕
|
||||
</p>
|
||||
|
||||
<div class="card mx-auto p-3" style="max-width: 400px; border-radius: 12px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); z-index: 200;">
|
||||
<h4 class="mb-3 text-center">🍽️ <strong><?= $model->food_name ?></strong></h4>
|
||||
<div class="row">
|
||||
<div class="col-6 text-right">
|
||||
<p class="mb-0"><strong>🔥 Calories</strong></p>
|
||||
<p class="mb-0"><strong>🍗 Protein</strong></p>
|
||||
<p class="mb-0"><strong>🥑 Fat</strong></p>
|
||||
<p class="mb-0"><strong>🍞 Carbs</strong></p>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<p class="mb-0"><?= $model->calories ?> kcal</p>
|
||||
<p class="mb-0"><?= $model->protein ?> g</p>
|
||||
<p class="mb-0"><?= $model->fat ?> g</p>
|
||||
<p class="mb-0"><?= $model->carbohydrates ?> g</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-5 mb-4 bg-transparent rounded-3">
|
||||
<div class="container-fluid py-5 text-center">
|
||||
<p><a class="btn btn-lg btn-primary" href="/meal/upload" style="z-index: 200;">Feed me more data! 🍔</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
62
frontend/views/meal/upload.php
Normal file
62
frontend/views/meal/upload.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
use yii\helpers\Html;
|
||||
use yii\widgets\ActiveForm;
|
||||
|
||||
/** @var yii\web\View $this */
|
||||
/** @var common\models\Meal $model */
|
||||
/** @var yii\widgets\ActiveForm $form */
|
||||
|
||||
$emoji = ['🍕', '🍔', '🍎', '🥑', '🥗', '🍣', '🍩', '🌮', '🍉', '🍞', '🍜', '🥩', '🍪', '🥕', '🧀', '🍓', '🍍', '🥒', '🍇', '🥞', '🦞', '🍗', '🍛'];
|
||||
$randEmojiIndex = array_rand($emoji, 1);
|
||||
$this->registerJS("
|
||||
let foodEmojis = ".json_encode($emoji).";
|
||||
let index = 0;
|
||||
let lastIndex = ".$randEmojiIndex.";
|
||||
|
||||
function cycleEmojis() {
|
||||
let newIndex;
|
||||
do {
|
||||
newIndex = Math.floor(Math.random() * foodEmojis.length);
|
||||
} while (newIndex === lastIndex); // Ensure it's different from the last one
|
||||
|
||||
lastIndex = newIndex; // Update lastIndex to track the last used emoji
|
||||
|
||||
$('#upload-title').fadeOut(200, function() {
|
||||
$(this).html('Upload Your ' + foodEmojis[newIndex]).fadeIn(200);
|
||||
});
|
||||
}
|
||||
|
||||
setInterval(cycleEmojis, 1500); // Change every 1.5 seconds
|
||||
|
||||
$('#mealform-picture').on('change', function(ev) {
|
||||
$('#submitButton').text('Processing...');
|
||||
$('#submitButton').attr('disabled', true);
|
||||
$(this).parents('form').submit();
|
||||
ev.preventDefault();
|
||||
});
|
||||
");
|
||||
?>
|
||||
|
||||
<div class="meal-form container mt-5">
|
||||
<div class="card shadow-sm p-4">
|
||||
<h5 id="upload-title" class="mb-3">Upload Your <?= $emoji[$randEmojiIndex] ?></h5>
|
||||
|
||||
<?php
|
||||
$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="mealform-picture" class="form-label">Your picture will automatically submit after selected. Just
|
||||
be patient.</label>
|
||||
<?= $form->field($model, 'picture')
|
||||
->fileInput([
|
||||
'class' => 'form-control',
|
||||
//'capture' => 'environment',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<?= Html::submitButton('Submit', ['id' => 'submitButton', 'class' => 'btn btn-success']) ?>
|
||||
</div>
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
/** @var yii\web\View $this */
|
||||
|
||||
$this->title = 'Sales Agent';
|
||||
$this->title = 'Calorie Thingy';
|
||||
|
||||
?>
|
||||
|
||||
<div class="alert alert-info" role="info">
|
||||
@@ -14,7 +15,7 @@ $this->title = 'Sales Agent';
|
||||
<h1 class="display-4">Calorie Ease</h1>
|
||||
<p class="fs-5 fw-light">Track your food with a picture!</p>
|
||||
<p>
|
||||
<a class="btn btn-lg btn-success" href="<?= Yii::$app->getUrlManager()->createUrl(['meal/create']) ?>">Log a meal</a>
|
||||
<a class="btn btn-lg btn-success" href="<?= Yii::$app->getUrlManager()->createUrl(['meal/upload']) ?>">Capture a meal</a>
|
||||
<a class="btn btn-lg btn-primary" href="<?= Yii::$app->getUrlManager()->createUrl(['summary']) ?>">View Summary</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user