AI and Food
This commit is contained in:
135
server/ai.js
135
server/ai.js
@@ -2,28 +2,28 @@ import {Ollama} from 'ollama'
|
|||||||
|
|
||||||
const ollama = new Ollama({ host: '172.29.186.121:11434' })
|
const ollama = new Ollama({ host: '172.29.186.121:11434' })
|
||||||
|
|
||||||
const response = await ollama.chat({
|
// const response = await ollama.chat({
|
||||||
model: 'llama3:latest',
|
// model: 'llama3:latest',
|
||||||
messages: [{ role: 'user', content:
|
// messages: [{ role: 'user', content:
|
||||||
`Generate a recipe for blueberry muffins:
|
// `Generate a recipe for blueberry muffins:
|
||||||
Format it in a json object like this and don't send any other text:
|
// Format it in a json object like this and don't send any other text:
|
||||||
{
|
// {
|
||||||
"name": "Blueberry Muffins",
|
// "name": "Blueberry Muffins",
|
||||||
"description": "A delicious and healthy blueberry muffin recipe",
|
// "description": "A delicious and healthy blueberry muffin recipe",
|
||||||
"nutritional_information": {},
|
// "nutritional_information": {},
|
||||||
ingredients: [
|
// ingredients: [
|
||||||
{
|
// {
|
||||||
"name": "flour",
|
// "name": "flour",
|
||||||
"quantity": "2 cups"
|
// "quantity": "2 cups"
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
instructions: [
|
// instructions: [
|
||||||
"Preheat oven to 350 degrees"
|
// "Preheat oven to 350 degrees"
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
`
|
// `
|
||||||
}],
|
// }],
|
||||||
});
|
// });
|
||||||
|
|
||||||
const questions = [
|
const questions = [
|
||||||
"Is this for breakfast, lunch, dinner, snack or dessert?",
|
"Is this for breakfast, lunch, dinner, snack or dessert?",
|
||||||
@@ -42,31 +42,27 @@ const questions = [
|
|||||||
"Are you looking for budget-friendly options, or are you willing to splurge a bit for a special meal?",
|
"Are you looking for budget-friendly options, or are you willing to splurge a bit for a special meal?",
|
||||||
"What’s the calorie range you want your meal to stay in? (You can specify yes or no)"
|
"What’s the calorie range you want your meal to stay in? (You can specify yes or no)"
|
||||||
]
|
]
|
||||||
const testAnswers =[
|
// const testAnswers =[
|
||||||
"Lunch",
|
// "Lunch",
|
||||||
"Italian",
|
// "Italian",
|
||||||
"Healthy",
|
// "Healthy",
|
||||||
"Cheese",
|
// "Cheese",
|
||||||
"Beans",
|
// "Beans",
|
||||||
"Moderate cook time",
|
// "Moderate cook time",
|
||||||
"Chicken",
|
// "Chicken",
|
||||||
"Medium",
|
// "Medium",
|
||||||
"Wine",
|
// "Wine",
|
||||||
"Regular Day",
|
// "Regular Day",
|
||||||
"Crispy",
|
// "Crispy",
|
||||||
"Oven,Microwave,Stove",
|
// "Oven,Microwave,Stove",
|
||||||
"few leftovers",
|
// "few leftovers",
|
||||||
"Budget-Friendly",
|
// "Budget-Friendly",
|
||||||
"800-1000"
|
// "800-1000"
|
||||||
]
|
// ]
|
||||||
|
|
||||||
const restrictions=[
|
export default class FDAI {
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
class aiClass{
|
|
||||||
constructor(){
|
constructor(){
|
||||||
this.ai = new Ollama({ host: '172.29.186.121:11434' });
|
this.ai = new Ollama({ host: process.env.AI_URL });
|
||||||
}
|
}
|
||||||
|
|
||||||
async suggestFood(questionAmount, answers, restrictions) {
|
async suggestFood(questionAmount, answers, restrictions) {
|
||||||
@@ -77,19 +73,52 @@ class aiClass{
|
|||||||
qaA += `Q${i}. ${answers[i]}\nA${i}. ${answers[i]}`
|
qaA += `Q${i}. ${answers[i]}\nA${i}. ${answers[i]}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await ollama.chat({
|
const response = await ollama.generate({
|
||||||
model: 'llama3:latest',
|
model: 'llama3:latest',
|
||||||
messages: [{ role: 'user', content:
|
format: "json",
|
||||||
`Give one food suggestion this question answers.
|
prompt:
|
||||||
|
`Give one food suggestion for these question answers and then generate a recipe.
|
||||||
|
${qaA}
|
||||||
|
Consider the following restrictions: ${restrictions.join(", ")}
|
||||||
|
Format it in a json object like this example:
|
||||||
|
{
|
||||||
|
"name": "Blueberry Muffins",
|
||||||
|
"description": "A delicious and healthy blueberry muffin recipe",
|
||||||
|
"cuisineType": "American",
|
||||||
|
"estimatedExpense": 5,
|
||||||
|
"mealType": "Breakfast",
|
||||||
|
"nutritionFacts": {
|
||||||
|
"calories": "350-400",
|
||||||
|
"fat": "15-20g",
|
||||||
|
"carbs": "30-40g",
|
||||||
|
"protein": "35-40g"
|
||||||
|
},
|
||||||
|
ingredients: [
|
||||||
|
{
|
||||||
|
"name": "flour",
|
||||||
|
"quantity": "2 cups"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
instructions: [
|
||||||
|
"Preheat oven to 350 degrees"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Do not send any other text other than the json object and or add extra text to the json object.
|
||||||
`
|
`
|
||||||
}],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.clearChatHistory();
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async clearChatHistory() {
|
||||||
|
await ollama.generate({
|
||||||
|
model: 'llama3:latest',
|
||||||
|
prompt: "clear all previous responses",
|
||||||
|
format: "json"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(response)
|
|
||||||
console.log(response.message.content)
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
import APIRoute from "../APIRoute.js";
|
import APIRoute from "../APIRoute.js";
|
||||||
|
|
||||||
export default class UsersAPI extends APIRoute {
|
import FDAI from "../ai.js";
|
||||||
|
|
||||||
|
const ai = new FDAI();
|
||||||
|
|
||||||
|
export default class RecipeAPI extends APIRoute {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('/recipes');
|
super('/recipes');
|
||||||
|
|
||||||
this.addSubRoute('/create', 'post', createRecipe);
|
this.addSubRoute('/create', 'post', this.createRecipe);
|
||||||
|
this.addSubRoute('/:id', 'get', this.get);
|
||||||
|
this.addSubRoute('/:id/rate', 'post', this.rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(req, res) {
|
async get(req, res) {
|
||||||
res.send('GET request');
|
let db = req.app.get('mongo').recipes;
|
||||||
}
|
|
||||||
|
|
||||||
async post(req, res) {
|
let result = await db.get(req.params.id);
|
||||||
res.send('POST request');
|
|
||||||
|
res.send(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createRecipe(req, res) {
|
async createRecipe(req, res) {
|
||||||
@@ -20,16 +26,37 @@ export default class UsersAPI extends APIRoute {
|
|||||||
|
|
||||||
let db = req.app.get('mongo').recipes;
|
let db = req.app.get('mongo').recipes;
|
||||||
|
|
||||||
let result = await db.create({
|
let aiResult = await ai.suggestFood(recipe.currentQuestion, recipe.answers, recipe.restrictions);
|
||||||
userID: recipe.userID,
|
|
||||||
ingredients: recipe.ingredients,
|
|
||||||
productName: recipe.productName,
|
|
||||||
nutritionFacts: recipe.nutritionFacts,
|
|
||||||
rating: recipe.rating,
|
|
||||||
cuisine: recipe.cuisine,
|
|
||||||
expense: recipe.expense,
|
|
||||||
mealType: recipe.mealType
|
|
||||||
});
|
|
||||||
|
|
||||||
|
let suggestFood = JSON.parse(aiResult.response);
|
||||||
|
|
||||||
|
let result = await db.create(suggestFood);
|
||||||
|
|
||||||
|
res.json(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async rate(req, res) {
|
||||||
|
let db = req.app.get('mongo').recipes;
|
||||||
|
|
||||||
|
let recipe = await db.get(req.params.id);
|
||||||
|
|
||||||
|
if (!recipe) {
|
||||||
|
res.status(404).send('Recipe not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rating = req.body.rating;
|
||||||
|
|
||||||
|
if (rating < 0 || rating > 5) {
|
||||||
|
res.status(400).send('Rating must be between 0 and 5');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
recipe.rating = rating;
|
||||||
|
|
||||||
|
let result = await db.update(req.params.id, { rating: rating });
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
import Users from "./collections/users.js";
|
import Users from "./collections/users.js";
|
||||||
|
import Recipes from "./collections/recipes.js";
|
||||||
|
|
||||||
export default class Mongo {
|
export default class Mongo {
|
||||||
constructor(uri) {
|
constructor(uri) {
|
||||||
this.connect(uri);
|
this.connect(uri);
|
||||||
this.users = new Users();
|
this.users = new Users();
|
||||||
|
this.recipes = new Recipes();
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect(uri) {
|
async connect(uri) {
|
||||||
|
|||||||
@@ -10,18 +10,16 @@ const reqString = {
|
|||||||
|
|
||||||
const recipesSchema = new mongoose.Schema({
|
const recipesSchema = new mongoose.Schema({
|
||||||
id: reqString,
|
id: reqString,
|
||||||
|
description: String,
|
||||||
userID: String,
|
userID: String,
|
||||||
ingredients: Array,
|
ingredients: Array,
|
||||||
productName: String,
|
instructions: Array,
|
||||||
|
name: String,
|
||||||
nutritionFacts: Object,
|
nutritionFacts: Object,
|
||||||
rating: Number,
|
rating: Number,
|
||||||
cuisine: String,
|
cuisine: String,
|
||||||
expense: Number,
|
expense: Number,
|
||||||
mealType: Object
|
mealType: Object
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}, { timestamps: true });
|
}, { timestamps: true });
|
||||||
|
|
||||||
export default class Recipes {
|
export default class Recipes {
|
||||||
@@ -39,18 +37,15 @@ export default class Recipes {
|
|||||||
id: Id,
|
id: Id,
|
||||||
userID: recipe.userID,
|
userID: recipe.userID,
|
||||||
ingredients: recipe.ingredients,
|
ingredients: recipe.ingredients,
|
||||||
productName: recipe.productName,
|
description: recipe.description,
|
||||||
|
name: recipe.name,
|
||||||
nutritionFacts: recipe.nutritionFacts,
|
nutritionFacts: recipe.nutritionFacts,
|
||||||
rating: recipe.rating,
|
|
||||||
cuisine: recipe.cuisine,
|
cuisine: recipe.cuisine,
|
||||||
expense: recipe.expense,
|
expense: recipe.expense,
|
||||||
mealType: recipe.mealType
|
mealType: recipe.mealType,
|
||||||
|
instructions: recipe.instructions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}, this.upsert);
|
}, this.upsert);
|
||||||
return await this.get(user.id);
|
return await this.get(Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(Id) {
|
async get(Id) {
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
</script>
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-md sticky-top py-3 navbar-dark" id="mainNav">
|
<nav class="navbar navbar-expand-md sticky-top py-3 navbar-dark" id="mainNav">
|
||||||
<div class="container"><a class="navbar-brand d-flex align-items-center" href="/"><span class="bs-icon-sm bs-icon-circle bs-icon-primary shadow d-flex justify-content-center align-items-center me-2 bs-icon"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-bezier">
|
<div class="container"><a class="navbar-brand d-flex align-items-center" href="/"><span class="bs-icon-sm bs-icon-circle bs-icon-primary shadow d-flex justify-content-center align-items-center me-2 bs-icon"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-bezier">
|
||||||
<path fill-rule="evenodd" d="M0 10.5A1.5 1.5 0 0 1 1.5 9h1A1.5 1.5 0 0 1 4 10.5v1A1.5 1.5 0 0 1 2.5 13h-1A1.5 1.5 0 0 1 0 11.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zm10.5.5A1.5 1.5 0 0 1 13.5 9h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1a1.5 1.5 0 0 1-1.5-1.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zM6 4.5A1.5 1.5 0 0 1 7.5 3h1A1.5 1.5 0 0 1 10 4.5v1A1.5 1.5 0 0 1 8.5 7h-1A1.5 1.5 0 0 1 6 5.5zM7.5 4a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5z"></path>
|
<path fill-rule="evenodd" d="M0 10.5A1.5 1.5 0 0 1 1.5 9h1A1.5 1.5 0 0 1 4 10.5v1A1.5 1.5 0 0 1 2.5 13h-1A1.5 1.5 0 0 1 0 11.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zm10.5.5A1.5 1.5 0 0 1 13.5 9h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1a1.5 1.5 0 0 1-1.5-1.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zM6 4.5A1.5 1.5 0 0 1 7.5 3h1A1.5 1.5 0 0 1 10 4.5v1A1.5 1.5 0 0 1 8.5 7h-1A1.5 1.5 0 0 1 6 5.5zM7.5 4a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5z"></path>
|
||||||
@@ -8,7 +12,12 @@
|
|||||||
<li class="nav-item"><a class="nav-link active" href="/">Home</a></li>
|
<li class="nav-item"><a class="nav-link active" href="/">Home</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="/survey">Survey</a></li>
|
<li class="nav-item"><a class="nav-link" href="/survey">Survey</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="/contacts">Contact Us</a></li>
|
<li class="nav-item"><a class="nav-link" href="/contacts">Contact Us</a></li>
|
||||||
</ul><a class="btn btn-primary shadow" role="button" href="signup.html" style="background: rgb(55, 99, 244);">Sign up</a>
|
</ul>
|
||||||
|
{ #if $page.data.authInfo }
|
||||||
|
<a class="btn btn-primary shadow" role="button" href="https://auth.fooddecisive.co/account" style="background: rgb(55, 99, 244);">Dashboard</a>
|
||||||
|
{ :else }
|
||||||
|
<a class="btn btn-primary shadow" role="button" href="https://auth.fooddecisive.co/" style="background: rgb(55, 99, 244);">Sign up</a>
|
||||||
|
{ /if }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -3,11 +3,7 @@
|
|||||||
import Survey from "./Survey.svelte";
|
import Survey from "./Survey.svelte";
|
||||||
export let parentDiv;
|
export let parentDiv;
|
||||||
|
|
||||||
console.log(parentDiv);
|
|
||||||
|
|
||||||
function open5Survey(questions) {
|
function open5Survey(questions) {
|
||||||
console.log(questions);
|
|
||||||
|
|
||||||
parentDiv.innerHTML = "";
|
parentDiv.innerHTML = "";
|
||||||
new Survey({
|
new Survey({
|
||||||
target: parentDiv,
|
target: parentDiv,
|
||||||
@@ -18,8 +14,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function open10Survey(questions) {
|
function open10Survey(questions) {
|
||||||
console.log(questions);
|
|
||||||
|
|
||||||
parentDiv.innerHTML = "";
|
parentDiv.innerHTML = "";
|
||||||
new Survey({
|
new Survey({
|
||||||
target: parentDiv,
|
target: parentDiv,
|
||||||
@@ -30,8 +24,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function open15Survey(questions) {
|
function open15Survey(questions) {
|
||||||
console.log(questions);
|
|
||||||
|
|
||||||
parentDiv.innerHTML = "";
|
parentDiv.innerHTML = "";
|
||||||
new Survey({
|
new Survey({
|
||||||
target: parentDiv,
|
target: parentDiv,
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
<script>
|
<script>
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import '../../survey.css';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
let formData = writable({
|
let formData = writable({
|
||||||
answers: [],
|
answers: [],
|
||||||
currentQuestion: 1
|
currentQuestion: 1,
|
||||||
|
userID: $page.data.authInfo ? $page.data.authInfo.id : null,
|
||||||
});
|
});
|
||||||
|
|
||||||
export let numQuestion = 0;
|
export let numQuestion = 0;
|
||||||
@@ -29,22 +33,54 @@
|
|||||||
"What’s the calorie range you want your meal to stay in? (You can specify yes or no)"
|
"What’s the calorie range you want your meal to stay in? (You can specify yes or no)"
|
||||||
];
|
];
|
||||||
|
|
||||||
console.log(numQuestion);
|
onMount(() => {
|
||||||
|
const buttons = document.querySelectorAll('.btn-info');
|
||||||
|
buttons.forEach(button => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
button.classList.toggle('active');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function nextQuestion() {
|
function nextQuestion() {
|
||||||
if ($formData.currentQuestion === numQuestion) return;
|
if ($formData.currentQuestion === numQuestion) return;
|
||||||
|
|
||||||
$formData.currentQuestion++;
|
$formData.currentQuestion++;
|
||||||
$formData.answers.push(inputEle.value);
|
$formData.answers.push(inputEle.value);
|
||||||
|
inputEle.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitForm() {
|
async function submitForm() {
|
||||||
|
|
||||||
|
let obj = $formData;
|
||||||
|
obj.answers.push(inputEle.value);
|
||||||
|
obj.restrictions = [];
|
||||||
|
|
||||||
|
const buttons = document.querySelectorAll('.btn-info');
|
||||||
|
buttons.forEach(button => {
|
||||||
|
if (button.classList.contains('active')) {
|
||||||
|
obj.restrictions.push(button.innerText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let recipeData = await fetch('/api/recipes/create', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(obj)
|
||||||
|
});
|
||||||
|
|
||||||
|
recipeData = await recipeData.json();
|
||||||
|
|
||||||
|
console.log(recipeData);
|
||||||
|
|
||||||
|
goto(`/food/${recipeData.id}`, { replaceState: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container py-5">
|
<div class="container">
|
||||||
<div class="row mb-5">
|
<div class="row mb-5">
|
||||||
<div class="col-md-8 col-xl-6 text-center mx-auto">
|
<div class="col-md-8 col-xl-6 text-center mx-auto">
|
||||||
<h2 class="fw-bold">Question {$formData.currentQuestion} </h2>
|
<h2 class="fw-bold">Question {$formData.currentQuestion} </h2>
|
||||||
@@ -57,7 +93,7 @@
|
|||||||
<div class="card-body mx-auto">
|
<div class="card-body mx-auto">
|
||||||
<p class="card-text" style="font-size: 40px;">
|
<p class="card-text" style="font-size: 40px;">
|
||||||
<strong>
|
<strong>
|
||||||
<span style="background-color: transparent;">{questions[$formData.currentQuestion]}</span>
|
<span style="background-color: transparent;">{questions[$formData.currentQuestion-1]}</span>
|
||||||
</strong>
|
</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -70,6 +106,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
<h4 class="card-title" style="text-align: center;">Select Dietary Restriction</h4>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="btn-group" role="group" style="width: 100%;">
|
||||||
|
<button class="btn btn-info" type="button">Vegetarian</button>
|
||||||
|
<button class="btn btn-info" type="button">Vegan</button>
|
||||||
|
<button class="btn btn-info" type="button">Gluten-free</button>
|
||||||
|
<button class="btn btn-info" type="button">Lactose-free</button>
|
||||||
|
<button class="btn btn-info" type="button">Nut-free</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="btn-group" role="group" style="width: 100%;">
|
||||||
|
<button class="btn btn-info" type="button">Halal</button>
|
||||||
|
<button class="btn btn-info" type="button">Kosher</button>
|
||||||
|
<button class="btn btn-info" type="button">Keto</button>
|
||||||
|
<button class="btn btn-info" type="button">Diabetic</button>
|
||||||
|
<button class="btn btn-info" type="button">Pescatarian</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
{#if $formData.currentQuestion === numQuestion}
|
{#if $formData.currentQuestion === numQuestion}
|
||||||
@@ -99,4 +160,9 @@
|
|||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: block;
|
||||||
|
min-width: 70% !important;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
7
src/lib/survey.css
Normal file
7
src/lib/survey.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
button.active {
|
||||||
|
background-color: #ff6a00 !important;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
import {createClient} from "@propelauth/javascript";
|
import {createClient} from "@propelauth/javascript";
|
||||||
|
const authClient = createClient({
|
||||||
|
|
||||||
export async function load() {
|
|
||||||
|
|
||||||
/*
|
|
||||||
const authClient = createClient({
|
|
||||||
authUrl: "https://auth.fooddecisive.co/",
|
authUrl: "https://auth.fooddecisive.co/",
|
||||||
enableBackgroundTokenRefresh: true,
|
enableBackgroundTokenRefresh: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export async function load() {
|
||||||
|
|
||||||
const authInfo = await authClient.getAuthenticationInfoOrNull();
|
const authInfo = await authClient.getAuthenticationInfoOrNull();
|
||||||
console.log("authInfo", authInfo)
|
console.log("authInfo", authInfo)
|
||||||
@@ -18,7 +15,6 @@ export async function load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
authInfo
|
authInfo: authInfo ? authInfo : null
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
<script>
|
|
||||||
import { page } from '$app/stores';
|
|
||||||
|
|
||||||
console.log($page.data);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<header class="bg-dark">
|
<header class="bg-dark">
|
||||||
<div class="container pt-4 pt-xl-5">
|
<div class="container pt-4 pt-xl-5">
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
<script>
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<section class="py-5">
|
|
||||||
<div class="container py-5">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body mx-auto">
|
|
||||||
<h4 class="card-title" style="font-size: 50px;">You Want</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="card" style="margin-bottom: 90px;margin-top: 20px;">
|
|
||||||
<div class="card-body mx-auto">
|
|
||||||
<p class="card-text mx-auto" style="font-size: 60px;font-weight: bold;text-align: center;">Butter Chicken</p>
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">Butter Chicken is a delicious Indian Meal. It was made by the British after they colonized the country.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xxl-6" style="margin-bottom: 20px;">
|
|
||||||
<div class="card" style="margin-bottom: 20px;">
|
|
||||||
<div class="card-body" style="margin-bottom: 20px;">
|
|
||||||
<h4 class="card-title mx-auto" style="text-align: center;margin-bottom: 20px;">Nutrition Facts</h4>
|
|
||||||
<p class="card-text" style="margin-bottom: 20px;">Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col" style="margin-bottom: 20px;">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="card-title" style="text-align: center;">Ingredients</h4>
|
|
||||||
<p class="card-text">Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="card-title" style="text-align: center;">Title</h4>
|
|
||||||
<p class="card-text">Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body mx-auto"><button class="btn btn-primary" type="button">Show Recipe</button></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="card-title" style="text-align: center;">Rate Your Generated Recipe!</h4>
|
|
||||||
<p class="card-text">Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
9
src/routes/food/[id]/+page.server.js
Normal file
9
src/routes/food/[id]/+page.server.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { PUBLIC_URL } from '$env/static/public';
|
||||||
|
|
||||||
|
export async function load({ params }) {
|
||||||
|
const foodID = params.id;
|
||||||
|
let foodData = await fetch(`${PUBLIC_URL}/api/recipes/${foodID}`);
|
||||||
|
foodData = await foodData.json();
|
||||||
|
|
||||||
|
return foodData;
|
||||||
|
}
|
||||||
96
src/routes/food/[id]/+page.svelte
Normal file
96
src/routes/food/[id]/+page.svelte
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<script>
|
||||||
|
// @ts-nocheck
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
let foodData = $page.data;
|
||||||
|
|
||||||
|
let nutritionFactsEle;
|
||||||
|
let IngredientsEle;
|
||||||
|
|
||||||
|
$: showRecipe = false;
|
||||||
|
|
||||||
|
function CLshowRecipe() {
|
||||||
|
showRecipe = true;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
for (const [key, value] of Object.entries(foodData.nutritionFacts)) {
|
||||||
|
nutritionFactsEle.innerText += `${key}: ${value}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
IngredientsEle.innerText = foodData.ingredients.map(ingredient => {
|
||||||
|
return `${ingredient.name}: ${ingredient.quantity}`;
|
||||||
|
}).join('\n');
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body mx-auto">
|
||||||
|
<h4 class="card-title" style="text-align: center; font-size: 50px;">You Want</h4>
|
||||||
|
<p class="card-text mx-auto" style="font-size: 60px;font-weight: bold;text-align: center;">{foodData.name}</p>
|
||||||
|
<p class="card-text">{foodData.description}</p>
|
||||||
|
</div>
|
||||||
|
{#if !showRecipe}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body mx-auto">
|
||||||
|
<button class="btn btn-primary" type="button" on:click={CLshowRecipe}>Show Recipe</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else }
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card" style="margin-bottom: 90px;margin-top: 20px;">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xxl-6" style="margin-bottom: 20px;">
|
||||||
|
<div class="card" style="margin-bottom: 20px;">
|
||||||
|
<div class="card-body" style="margin-bottom: 20px;">
|
||||||
|
<h2 class="card-title mx-auto" style="text-align: center;margin-bottom: 20px;">Nutrition Facts</h2>
|
||||||
|
<p class="card-text" style="text-align:center; margin-bottom: 20px;" bind:this={nutritionFactsEle}></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col" style="margin-bottom: 20px;">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title" style="text-align: center;">Ingredients</h2>
|
||||||
|
<p class="card-text" style="text-align: center;" bind:this={IngredientsEle}></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title" style="text-align: center;">Instructions</h2>
|
||||||
|
<p class="card-text">
|
||||||
|
<ul>
|
||||||
|
{ #each foodData.instructions as instruction }
|
||||||
|
<li>{instruction}</li>
|
||||||
|
{ /each }
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<h4 class="card-title" style="text-align: center;">Rate Your Suggested Food!</h4>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="form" class="card" style="padding-top: 20px;padding-bottom: 100px;">
|
<div id="form" class="card" style="padding-top: 20px;padding-bottom: 100px;">
|
||||||
<div bind:this={parentDiv} class="card-body mx-auto"></div>
|
<div bind:this={parentDiv} class="card-body"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
Reference in New Issue
Block a user