Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Juan Montilla
/
TBW2223_equipo12
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
b09851d8
authored
May 07, 2023
by
Juan Montilla
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
ajax
parent
83dd03bb
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
840 additions
and
822 deletions
app/Config/Routes.php
app/Controllers/RecipesController.php
app/Models/RecipesModel.php
app/Views/pages/home.php
app/Views/pages/recipe_view.php
app/Views/templates/header.php
public/css/style.css
public/imagenes/2729270.png
public/js/insert.js
public/js/main.js
app/Config/Routes.php
View file @
b09851d8
...
...
@@ -38,6 +38,8 @@ $routes->match(['get', 'post'], '/registerAjax', [User::class, 'registerAjax']);
$routes
->
match
([
'get'
],
'/home'
,
[
User
::
class
,
'user_ok'
]);
$routes
->
get
(
'/recipe/(:num)'
,
'RecipesController::view_recipe/$1'
);
// Ruta para obtener una imagen de una receta dado un id
$routes
->
get
(
'recipe/image/(:num)'
,
'RecipesController::show_image/$1'
);
...
...
@@ -46,15 +48,15 @@ $routes->get('/insert_recipe', 'InsertRecipeController::index');
$routes
->
match
([
'get'
,
'post'
],
'/search_ingredient'
,
'InsertRecipeController::search_ingredient'
);
$routes
->
post
(
'/insert_recipe'
,
'InsertRecipeController::insert_recipe'
);
// Ruta para la búsqueda de recetas
$routes
->
match
([
'get'
,
'post'
],
'/search_recipe'
,
'RecipesController::search_recipe'
);
$routes
->
get
(
'login'
,
'Pages::viewLogin'
);
$routes
->
get
(
'users'
,
'User::list'
);
$routes
->
get
(
'home'
,
'Pages::prueba'
);
$routes
->
get
(
'(:segment)'
,
'Home::index'
);
$routes
->
get
(
'/recipe/(:num)'
,
'RecipesController::view_recipe/$1'
);
...
...
app/Controllers/RecipesController.php
View file @
b09851d8
...
...
@@ -25,7 +25,7 @@ class RecipesController extends Controller
];
return
view
(
'templates/header'
,
$data
)
.
view
(
'pages/recipe_view'
,
$data
)
.
view
(
'pages/recipe_view'
)
.
view
(
'templates/footer'
);
}
...
...
@@ -45,25 +45,11 @@ class RecipesController extends Controller
}
}
//public function search_recipe() {
// Obtener la consulta de búsqueda desde el formulario
// $query = $this->request->getVar('query');
// Cargar el modelo de ingredientes (si no lo has hecho)
//$recipesModel = new \App\Models\RecipesModel();
// Buscar ingredientes en la base de datos que coincidan con la consulta
// $recipes = $recipesModel->search_recipe($query);
// Devolver los ingredientes coincidentes en formato JSON
// return $this->response->setJSON($recipes);
// }
public
function
search_recipe
()
{
$query
=
$this
->
request
->
getVar
(
'query'
);
$recipesModel
=
new
\App\Models\RecipesModel
();
$recipes
=
$recipesModel
->
search
_r
ecipe
(
$query
);
$recipes
=
$recipesModel
->
search
R
ecipe
(
$query
);
return
$this
->
response
->
setJSON
(
$recipes
);
}
}
\ No newline at end of file
app/Models/RecipesModel.php
View file @
b09851d8
...
...
@@ -3,7 +3,7 @@ namespace App\Models;
use
CodeIgniter\Model
;
class
r
ecipesModel
extends
Model
class
R
ecipesModel
extends
Model
{
protected
$table
=
'recipes'
;
protected
$primaryKey
=
'id'
;
...
...
@@ -11,7 +11,7 @@ class recipesModel extends Model
protected
$returnType
=
'object'
;
# 'object' or 'array'
protected
$useSoftDeletes
=
false
;
# true if you expect to recover data
# Fields that can be set during save, insert, or update methods
protected
$allowedFields
=
[
'id'
,
'name'
,
'season'
,
'origin'
,
'photo'
,
'is_vegan'
,
'description'
,
'instructions'
,
'link'
];
protected
$allowedFields
=
[
'id'
,
'name'
,
'season'
,
'origin'
,
'photo'
,
'is_vegan'
,
'description'
,
'instructions'
,
'link'
];
protected
$useTimestamps
=
false
;
# no timestamps on inserts and updates
# Do not use validations rules (for the time being...)
protected
$validationRules
=
[];
...
...
@@ -35,7 +35,8 @@ class recipesModel extends Model
return
$this
->
insert
(
$data
);
}
public
function
get_recipe_ingredients
(
$recipe_id
)
{
public
function
get_recipe_ingredients
(
$recipe_id
)
{
$builder
=
$this
->
db
->
table
(
'recipes_ingredient'
);
$builder
->
select
(
'ingredient.name, ingredient.icon, recipes_ingredient.amount'
);
$builder
->
join
(
'ingredient'
,
'recipes_ingredient.id_ingredient = ingredient.id'
);
...
...
@@ -43,21 +44,22 @@ class recipesModel extends Model
$query
=
$builder
->
get
();
return
$query
->
getResult
();
}
/* public function search_recipe($query)
{
if ($query) {
return $this->like('name', $query)->findAll();
}
return [];
} */
public
function
search_recipe
(
$query
)
public
function
searchRecipe
(
$query
)
{
if
(
$query
)
{
// Seleccionar todas las columnas excepto 'photo'
$this
->
select
(
'id, name, season, origin, is_vegan, description, instructions, link'
);
return
$this
->
like
(
'name'
,
$query
)
->
findAll
();
}
return
[];
}
}
\ No newline at end of file
app/Views/pages/home.php
View file @
b09851d8
<!-- ======= Sidebar ======= -->
<aside
id=
"sidebar"
class=
"sidebar"
>
<ul
class=
"sidebar-nav"
id=
"sidebar-nav"
>
<li
class=
"nav-item"
>
<a
class=
"nav-link "
href=
"index.html"
>
<i
class=
"bi bi-grid"
></i>
<span>
Recetas
</span>
</a>
</li>
<!-- End Dashboard Nav -->
<!-- Filtro 1-->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
data-bs-target=
"#tables-nav"
data-bs-toggle=
"collapse"
href=
"#"
>
<i
class=
"bi bi-layout-text-window-reverse"
></i><span>
Filtro Vegano
</span><i
class=
"bi bi-chevron-down ms-auto"
></i>
</a>
<ul
id=
"tables-nav"
class=
"nav-content collapse "
data-bs-parent=
"#sidebar-nav"
>
<!--Contenido del dropdown-->
<ul
class=
"vegan-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxOne"
value=
"Order one"
>
<label
for=
"checkboxOne"
>
Recetas Veganas
</label>
</li>
</ul>
</ul>
</li>
<!-- Fin Filtro 1 -->
<!-- Filtro 1-->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
data-bs-target=
"#tables-nav2"
data-bs-toggle=
"collapse"
href=
"#"
>
<i
class=
"bi bi-layout-text-window-reverse"
></i><span>
Filtro 2
</span><i
class=
"bi bi-chevron-down ms-auto"
></i>
</a>
<ul
id=
"tables-nav2"
class=
"nav-content collapse "
data-bs-parent=
"#sidebar-nav"
>
<!--Contenido del dropdown-->
<ul
class=
"indian-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxFour"
value=
"Order four"
>
<label
for=
"checkboxFour"
>
India
</label>
</li>
</ul>
<ul
class=
"french-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxFive"
value=
"Order five"
>
<label
for=
"checkboxFive"
>
Francia
</label>
</li>
</ul>
<ul
class=
"chinese-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxSix"
value=
"Order six"
>
<label
for=
"checkboxSix"
>
China
</label>
</li>
</ul>
<ul
class=
"mexican-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxSeven"
value=
"Order seven"
>
<label
for=
"checkboxSeven"
>
México
</label>
</li>
</ul>
<ul
class=
"spanish-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxEight"
value=
"Order eigth"
>
<label
for=
"checkboxEight"
>
España
</label>
</li>
</ul>
<ul
class=
"japanese-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxNine"
value=
"Order nine"
>
<label
for=
"checkboxNine"
>
Japón
</label>
</li>
</ul>
</ul>
</li>
<!-- Fin Filtro 1 -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
data-bs-target=
"#tables-nav3"
data-bs-toggle=
"collapse"
href=
"#"
>
<i
class=
"bi bi-layout-text-window-reverse"
></i><span>
Estaciones
</span><i
class=
"bi bi-chevron-down ms-auto"
></i>
</a>
<ul
id=
"tables-nav3"
class=
"nav-content collapse "
data-bs-parent=
"#sidebar-nav"
>
<!--Contenido del dropdown-->
<ul
class=
"winter-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxTen"
value=
"Order ten"
>
<label
for=
"checkboxTen"
>
Invierno
</label>
</li>
</ul>
<ul
class=
"spring-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxEleven"
value=
"Order eleven"
>
<label
for=
"checkboxEleven"
>
Primavera
</label>
</li>
</ul>
<ul
class=
"summer-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxTwelve"
value=
"Order twelve"
>
<label
for=
"checkboxTwelve"
>
Verano
</label>
</li>
</ul>
<ul
class=
"autumn-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkbox13"
value=
"Order 13"
>
<label
for=
"checkbox13"
>
Otoño
</label>
</li>
</ul>
</ul>
</li>
<!-- Fin Filtro 1 -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
href=
"/insert_recipe"
>
<i
class=
"bi bi-file-earmark"
></i>
<span>
Subir receta
</span>
</a>
</li>
<!-- End Profile Page Nav -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
href=
"https://www.instagram.com/salvaperfectti/"
>
<i
class=
"bi bi-envelope"
></i>
<span>
Contacto
</span>
</a>
</li>
<!-- End Contact Page Nav -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
href=
"/login"
>
<i
class=
"bi bi-box-arrow-in-right"
></i>
<span>
Registro/Login
</span>
</a>
</li>
<!-- End Login Page Nav -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
href=
"http://www.homerswebpage.com/"
>
<i
class=
"bi bi-dash-circle"
></i>
<span>
Error 404
</span>
</a>
</li>
<!-- End Error 404 Page Nav -->
</ul>
</aside>
<!-- End Sidebar-->
<main
id=
"main"
class=
"main"
>
<div
class=
"pagetitle"
>
...
...
@@ -179,51 +20,50 @@
foreach
(
$recipes
as
$row
)
{
$ingredients
=
$recipesModel
->
get_recipe_ingredients
(
$row
->
id
);
?>
<!-- Inicio de la tarjeta de la receta -->
<div
class=
"recipe-card-wrapper"
>
<a
href=
"
<?php
echo
base_url
(
'recipe/'
.
$row
->
id
);
?>
"
class=
"recipe-card-link"
>
<div
class=
"card info-card sales-card"
>
<div
class=
"row"
>
<div
class=
"col-md-3 imagen-container"
>
<img
src=
"
<?php
echo
base_url
(
'recipe/image/'
.
$row
->
id
);
?>
"
alt=
""
class=
"img-fluid rounded-start"
>
</div>
<div
class=
"card info-card sales-card"
onclick=
"window.location.href='
<?php
echo
base_url
(
'recipe/'
.
$row
->
id
);
?>
'"
>
<a
href=
"
<?php
echo
base_url
(
'recipe/'
.
$row
->
id
);
?>
"
>
</a>
<div
class=
"row flex-nowrap"
>
<div
class=
"col-lg-3 col-md-4 col-sm-12 imagen-container"
>
<img
src=
"
<?php
echo
base_url
(
'recipe/image/'
.
$row
->
id
);
?>
"
alt=
""
class=
"img-fluid rounded-start"
>
</div>
<div
class=
"col-md-9
"
>
<div
class=
"filter"
>
<a
class=
"icon"
href=
"#"
data-bs-toggle=
"dropdown"
><i
class=
"bi bi-three-dots"
></i></a>
<ul
class=
"dropdown-menu dropdown-menu-end dropdown-menu-arrow"
>
<li
class=
"dropdown-header text-start"
>
<h6>
Opciones
</h6>
</li>
<li><a
class=
"dropdown-item"
href=
"#"
>
Guardar
</a></li>
<li><a
class=
"dropdown-item"
href=
"#"
>
Compartir
</a></li>
</ul>
</div>
<div
class=
"col-lg-9 col-md-8 col-sm-12
"
>
<div
class=
"filter"
>
<a
class=
"icon"
href=
"#"
data-bs-toggle=
"dropdown"
><i
class=
"bi bi-three-dots"
></i></a>
<ul
class=
"dropdown-menu dropdown-menu-end dropdown-menu-arrow"
>
<li
class=
"dropdown-header text-start"
>
<h6>
Opciones
</h6>
</li>
<li><a
class=
"dropdown-item"
href=
"#"
>
Guardar
</a></li>
<li><a
class=
"dropdown-item"
href=
"#"
>
Compartir
</a></li>
</ul>
</div>
<div
class=
"card-body"
>
<h5
class=
"card-title"
>
<?php
echo
$row
->
name
;
?>
<span>
|
<?php
echo
$row
->
origin
;
?>
</span>
</h5>
<!--ingredientes-->
<?php
foreach
(
$ingredients
as
$ingredient
)
{
?>
<div
class=
"chip"
title=
"Cantidad:
<?php
echo
$ingredient
->
amount
;
?>
"
>
<img
src=
"imagenes/ingredientes/
<?php
echo
$ingredient
->
icon
;
?>
"
>
<b
style=
"font-size: 14px"
>
<?php
echo
$ingredient
->
name
;
?>
</b>
</div>
<?php
}
?>
<!--fin ingredientes-->
<div
class=
"card-body"
>
<h5
class=
"card-title"
>
<?php
echo
$row
->
name
;
?>
<span>
|
<?php
echo
$row
->
origin
;
?>
</span>
</h5>
<!--ingredientes-->
<?php
foreach
(
$ingredients
as
$ingredient
)
{
?>
<div
class=
"chip"
title=
"Cantidad:
<?php
echo
$ingredient
->
amount
;
?>
"
>
<img
src=
"imagenes/ingredientes/
<?php
echo
$ingredient
->
icon
;
?>
"
>
<b
style=
"font-size: 14px"
>
<?php
echo
$ingredient
->
name
;
?>
</b>
</div>
</div>
<?php
}
?>
<!--fin ingredientes-->
</div>
</div>
</
a
>
</
div
>
</div>
<!-- Fin de la tarjeta de la receta -->
<?php
}
...
...
app/Views/pages/recipe_view.php
View file @
b09851d8
<?php
function
getYoutubeVideoId
(
$url
)
{
function
getYoutubeVideoId
(
$url
)
{
$pattern
=
'/^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/i'
;
preg_match
(
$pattern
,
$url
,
$matches
);
return
isset
(
$matches
[
1
])
?
$matches
[
1
]
:
null
;
...
...
@@ -7,112 +8,124 @@ function getYoutubeVideoId($url) {
?>
<style>
body
{
font-family
:
Arial
,
sans-serif
;
margin
:
0
;
padding
:
0
;
}
.container
{
max-width
:
960px
;
margin
:
0
auto
;
padding
:
20px
;
}
.recipe-header
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
margin-bottom
:
30px
;
}
.recipe-header
img
{
width
:
100%
;
max-width
:
600px
;
height
:
auto
;
object-fit
:
cover
;
border-radius
:
8px
;
}
.ingredient-list
{
display
:
flex
;
flex-wrap
:
wrap
;
list-style-type
:
none
;
padding
:
0
;
margin
:
0
;
margin-bottom
:
30px
;
}
.ingredient-item
{
display
:
flex
;
align-items
:
center
;
width
:
50%
;
padding
:
5px
0
;
}
.ingredient-item
img
{
width
:
30px
;
height
:
30px
;
margin-right
:
10px
;
}
.instructions
{
white-space
:
pre-line
;
}
.video-container
{
position
:
relative
;
padding-bottom
:
56.25%
;
/* Relación de aspecto 16:9 */
height
:
0
;
overflow
:
hidden
;
}
.video-container
iframe
{
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
100%
;
height
:
100%
;
}
</style>
<main
id=
"mainview"
class=
"mainview"
>
<section
class=
"section dashboard"
>
<div
class=
"container"
>
<div
class=
"recipe-header"
>
<h1>
Receta:
</h1>
<h1>
<?php
echo
$recipe
->
name
;
?>
</h1>
<img
src=
"
<?php
echo
base_url
(
'recipe/image/'
.
$recipe
->
id
);
?>
"
alt=
"
<?php
echo
$recipe
->
name
;
?>
"
/>
</div>
<p>
<?php
echo
$recipe
->
description
;
?>
</p>
<h2>
Ingredientes
</h2>
<ul
class=
"ingredient-list"
>
<?php
foreach
(
$ingredients
as
$ingredient
)
{
?>
<li
class=
"ingredient-item"
>
<img
src=
"../imagenes/ingredientes/
<?php
echo
$ingredient
->
icon
;
?>
"
alt=
"
<?php
echo
$ingredient
->
name
;
?>
"
/>
<span>
<?php
echo
$ingredient
->
name
;
?>
:
<?php
echo
$ingredient
->
amount
;
?>
</span>
</li>
<?php
}
?>
</ul>
<h2>
Instrucciones
</h2>
<p
class=
"instructions"
>
<?php
echo
$recipe
->
instructions
;
?>
</p>
<?php
if
(
!
empty
(
$recipe
->
link
))
:
?>
<?php
$videoId
=
getYoutubeVideoId
(
$recipe
->
link
);
?>
<?php
if
(
$videoId
)
:
?>
<h2>
Video de la receta
</h2>
<div
class=
"video-container"
>
<iframe
width=
"560"
height=
"315"
src=
"https://www.youtube.com/embed/
<?php
echo
$videoId
;
?>
"
title=
"YouTube video player"
frameborder=
"0"
allow=
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
></iframe>
</div>
body
{
font-family
:
Arial
,
sans-serif
;
margin
:
0
;
padding
:
0
;
}
.container
{
max-width
:
960px
;
margin
:
0
auto
;
padding
:
20px
;
}
.recipe-header
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
margin-bottom
:
30px
;
}
.recipe-header
img
{
width
:
100%
;
max-width
:
600px
;
height
:
auto
;
object-fit
:
cover
;
border-radius
:
8px
;
}
.ingredient-list
{
display
:
flex
;
flex-wrap
:
wrap
;
list-style-type
:
none
;
padding
:
0
;
margin
:
0
;
margin-bottom
:
30px
;
}
.ingredient-item
{
display
:
flex
;
align-items
:
center
;
width
:
50%
;
padding
:
5px
0
;
}
.ingredient-item
img
{
width
:
30px
;
height
:
30px
;
margin-right
:
10px
;
}
.instructions
{
white-space
:
pre-line
;
}
.video-container
{
position
:
relative
;
padding-bottom
:
56.25%
;
/* Relación de aspecto 16:9 */
height
:
0
;
overflow
:
hidden
;
}
.video-container
iframe
{
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
100%
;
height
:
100%
;
}
</style>
<main
id=
"main"
class=
"main"
>
<section
class=
"section dashboard"
>
<div
class=
"container"
>
<div
class=
"recipe-header"
>
<h1>
<?php
echo
$recipe
->
name
;
?>
</h1>
<img
src=
"
<?php
echo
base_url
(
'recipe/image/'
.
$recipe
->
id
);
?>
"
alt=
"
<?php
echo
$recipe
->
name
;
?>
"
/>
</div>
<p>
<?php
echo
$recipe
->
description
;
?>
</p>
<h2>
Ingredientes
</h2>
<ul
class=
"ingredient-list"
>
<?php
foreach
(
$ingredients
as
$ingredient
)
{
?>
<li
class=
"ingredient-item"
>
<img
src=
"../imagenes/ingredientes/
<?php
echo
$ingredient
->
icon
;
?>
"
alt=
"
<?php
echo
$ingredient
->
name
;
?>
"
/>
<span>
<?php
echo
$ingredient
->
name
;
?>
:
<?php
echo
$ingredient
->
amount
;
?>
</span>
</li>
<?php
}
?>
</ul>
<h2>
Instrucciones
</h2>
<p
class=
"instructions"
>
<?php
echo
$recipe
->
instructions
;
?>
</p>
<?php
if
(
!
empty
(
$recipe
->
link
))
:
?>
<?php
$videoId
=
getYoutubeVideoId
(
$recipe
->
link
);
?>
<?php
if
(
$videoId
)
:
?>
<h2>
Video de la receta
</h2>
<div
class=
"video-container"
>
<iframe
width=
"560"
height=
"315"
src=
"https://www.youtube.com/embed/
<?php
echo
$videoId
;
?>
"
title=
"YouTube video player"
frameborder=
"0"
allow=
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
></iframe>
</div>
<?php
endif
;
?>
<?php
endif
;
?>
<?php
endif
;
?>
</div>
</div>
</section>
</main>
<!-- End #main -->
\ No newline at end of file
app/Views/templates/header.php
View file @
b09851d8
...
...
@@ -33,7 +33,7 @@
<script
src=
"https://code.jquery.com/jquery-3.6.4.min.js"
integrity=
"sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8="
crossorigin=
"anonymous"
></script>
<script
src=
"js/main.js"
></script>
</head>
...
...
@@ -55,15 +55,15 @@
<i
class=
"bi bi-list toggle-sidebar-btn"
></i>
</div>
<!-- End Logo -->
<!-- Barra de búsqueda -->
<div
class=
"search-bar"
>
<form
class=
"search-form d-flex align-items-center"
method=
"POST"
action=
"#"
>
<input
type=
"text"
id=
"search-query"
name=
"query"
placeholder=
"Buscar por receta..."
title=
"Enter search keyword"
>
</form>
<div
id=
"recipe_dropdown"
class=
"recipe-dropdown"
>
<ul
id=
"recipe_list"
class=
"recipe-list list-unstyled"
></ul>
</div>
</div>
<form
class=
"search-form d-flex align-items-center"
method=
"POST"
action=
"#"
>
<input
type=
"text"
id=
"search-query"
name=
"query"
placeholder=
"Buscar por receta..."
title=
"Enter search keyword"
>
</form>
<ul
id=
"recipe_list"
class=
"ingredients-list list-unstyled"
></ul>
</div>
<!-- Fin barra de búsqueda -->
...
...
@@ -154,4 +154,163 @@
</ul>
</nav>
<!-- End Icons Navigation -->
</header>
<!-- End Header -->
\ No newline at end of file
</header>
<!-- End Header -->
<!-- ======= Sidebar ======= -->
<aside
id=
"sidebar"
class=
"sidebar"
>
<ul
class=
"sidebar-nav"
id=
"sidebar-nav"
>
<li
class=
"nav-item"
>
<a
class=
"nav-link "
href=
"index.html"
>
<i
class=
"bi bi-grid"
></i>
<span>
Recetas
</span>
</a>
</li>
<!-- End Dashboard Nav -->
<!-- Filtro 1-->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
data-bs-target=
"#tables-nav"
data-bs-toggle=
"collapse"
href=
"#"
>
<i
class=
"bi bi-layout-text-window-reverse"
></i><span>
Filtro Vegano
</span><i
class=
"bi bi-chevron-down ms-auto"
></i>
</a>
<ul
id=
"tables-nav"
class=
"nav-content collapse "
data-bs-parent=
"#sidebar-nav"
>
<!--Contenido del dropdown-->
<ul
class=
"vegan-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxOne"
value=
"Order one"
>
<label
for=
"checkboxOne"
>
Recetas Veganas
</label>
</li>
</ul>
</ul>
</li>
<!-- Fin Filtro 1 -->
<!-- Filtro 1-->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
data-bs-target=
"#tables-nav2"
data-bs-toggle=
"collapse"
href=
"#"
>
<i
class=
"bi bi-layout-text-window-reverse"
></i><span>
Filtro 2
</span><i
class=
"bi bi-chevron-down ms-auto"
></i>
</a>
<ul
id=
"tables-nav2"
class=
"nav-content collapse "
data-bs-parent=
"#sidebar-nav"
>
<!--Contenido del dropdown-->
<ul
class=
"indian-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxFour"
value=
"Order four"
>
<label
for=
"checkboxFour"
>
India
</label>
</li>
</ul>
<ul
class=
"french-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxFive"
value=
"Order five"
>
<label
for=
"checkboxFive"
>
Francia
</label>
</li>
</ul>
<ul
class=
"chinese-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxSix"
value=
"Order six"
>
<label
for=
"checkboxSix"
>
China
</label>
</li>
</ul>
<ul
class=
"mexican-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxSeven"
value=
"Order seven"
>
<label
for=
"checkboxSeven"
>
México
</label>
</li>
</ul>
<ul
class=
"spanish-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxEight"
value=
"Order eigth"
>
<label
for=
"checkboxEight"
>
España
</label>
</li>
</ul>
<ul
class=
"japanese-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxNine"
value=
"Order nine"
>
<label
for=
"checkboxNine"
>
Japón
</label>
</li>
</ul>
</ul>
</li>
<!-- Fin Filtro 1 -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
data-bs-target=
"#tables-nav3"
data-bs-toggle=
"collapse"
href=
"#"
>
<i
class=
"bi bi-layout-text-window-reverse"
></i><span>
Estaciones
</span><i
class=
"bi bi-chevron-down ms-auto"
></i>
</a>
<ul
id=
"tables-nav3"
class=
"nav-content collapse "
data-bs-parent=
"#sidebar-nav"
>
<!--Contenido del dropdown-->
<ul
class=
"winter-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxTen"
value=
"Order ten"
>
<label
for=
"checkboxTen"
>
Invierno
</label>
</li>
</ul>
<ul
class=
"spring-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxEleven"
value=
"Order eleven"
>
<label
for=
"checkboxEleven"
>
Primavera
</label>
</li>
</ul>
<ul
class=
"summer-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkboxTwelve"
value=
"Order twelve"
>
<label
for=
"checkboxTwelve"
>
Verano
</label>
</li>
</ul>
<ul
class=
"autumn-cboxtags"
>
<li>
<input
type=
"checkbox"
id=
"checkbox13"
value=
"Order 13"
>
<label
for=
"checkbox13"
>
Otoño
</label>
</li>
</ul>
</ul>
</li>
<!-- Fin Filtro 1 -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
href=
"/insert_recipe"
>
<i
class=
"bi bi-file-earmark"
></i>
<span>
Subir receta
</span>
</a>
</li>
<!-- End Profile Page Nav -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
href=
"https://www.instagram.com/salvaperfectti/"
>
<i
class=
"bi bi-envelope"
></i>
<span>
Contacto
</span>
</a>
</li>
<!-- End Contact Page Nav -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
href=
"/login"
>
<i
class=
"bi bi-box-arrow-in-right"
></i>
<span>
Registro/Login
</span>
</a>
</li>
<!-- End Login Page Nav -->
<li
class=
"nav-item"
>
<a
class=
"nav-link collapsed"
href=
"http://www.homerswebpage.com/"
>
<i
class=
"bi bi-dash-circle"
></i>
<span>
Error 404
</span>
</a>
</li>
<!-- End Error 404 Page Nav -->
</ul>
</aside>
<!-- End Sidebar-->
\ No newline at end of file
public/css/style.css
View file @
b09851d8
...
...
@@ -360,6 +360,26 @@ h6 {
.header
.search-bar
{
min-width
:
360px
;
padding
:
0
20px
;
position
:
relative
;
}
#recipe_list
{
position
:
absolute
;
top
:
100%
;
left
:
0
;
z-index
:
1
;
width
:
100%
;
max-height
:
200px
;
overflow-y
:
auto
;
background-color
:
#fff
;
border-top
:
none
;
border-radius
:
0
0
.25rem
.25rem
;
padding
:
0
;
margin
:
0
;
}
.recipe-item
{
cursor
:
pointer
;
}
@media
(
max-width
:
1199px
)
{
...
...
@@ -789,10 +809,7 @@ h6 {
}
/* Info Cards */
.dashboard
.info-card
{
padding-bottom
:
10px
;
}
s
.dashboard
.info-card
h6
{
font-size
:
28px
;
color
:
#012970
;
...
...
@@ -904,12 +921,6 @@ h6 {
padding-left
:
0
;
}
.recipe-card-link
{
display
:
block
;
text-decoration
:
none
;
color
:
inherit
;
}
.dashboard
.news
p
{
font-size
:
14px
;
color
:
#777777
;
...
...
public/imagenes/2729270.png
0 → 100644
View file @
b09851d8
48.8 KB
public/js/insert.js
View file @
b09851d8
...
...
@@ -11,21 +11,21 @@ const recipeForm = document.querySelector("form.my-form");
recipeForm
.
addEventListener
(
"submit"
,
function
(
event
)
{
const
selectedIngredients
=
Array
.
from
(
document
.
querySelectorAll
(
".selected-ingredient"
));
const
ingredientsData
=
selectedIngredients
.
map
((
ingredientElem
)
=>
{
return
{
id
:
ingredientElem
.
dataset
.
ingredientId
,
amount
:
ingredientElem
.
querySelector
(
".ingredient-amount"
).
textContent
,
};
return
{
id
:
ingredientElem
.
dataset
.
ingredientId
,
amount
:
ingredientElem
.
querySelector
(
".ingredient-amount"
).
textContent
,
};
});
const
hiddenInput
=
document
.
createElement
(
"input"
);
hiddenInput
.
type
=
"hidden"
;
hiddenInput
.
name
=
"selected_ingredients"
;
hiddenInput
.
value
=
JSON
.
stringify
(
ingredientsData
);
recipeForm
.
appendChild
(
hiddenInput
);
});
});
// Array para almacenar palabras clave seleccionadas
let
ingredients
=
[];
...
...
@@ -35,7 +35,7 @@ function searchIngredients(query) {
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/x-www-form-urlencoded'
,
'X-Requested-With'
:
'XMLHttpRequest'
// Añadir esta línea
'X-Requested-With'
:
'XMLHttpRequest'
},
body
:
'query='
+
encodeURIComponent
(
query
)
})
...
...
@@ -109,38 +109,38 @@ function removeIngredient(ingredient) {
function
updateSelectedIngredients
()
{
// Limpiar el campo de selección
selectedIngredients
.
innerHTML
=
''
;
// Agregar cada ingrediente seleccionado al campo de selección
ingredients
.
forEach
(
function
(
ingredient
)
{
const
ingredientElement
=
document
.
createElement
(
'div'
);
ingredientElement
.
classList
.
add
(
'selected-ingredient'
);
ingredientElement
.
setAttribute
(
'data-ingredient-id'
,
ingredient
.
id
);
// Crear el elemento de imagen para el icono del ingrediente
const
iconElement
=
document
.
createElement
(
'img'
);
iconElement
.
classList
.
add
(
'ingredient-icon'
);
iconElement
.
src
=
'../imagenes/ingredientes/'
+
ingredient
.
icon
;
ingredientElement
.
appendChild
(
iconElement
);
// Agregar el nombre del ingrediente y la cantidad
const
ingredientNameAndQuantity
=
document
.
createElement
(
'span'
);
ingredientNameAndQuantity
.
textContent
=
`
${
ingredient
.
name
}
(
${
ingredient
.
quantity
}
)`
;
ingredientNameAndQuantity
.
classList
.
add
(
'ingredient-amount'
);
ingredientElement
.
appendChild
(
ingredientNameAndQuantity
);
// Agregar el botón para eliminar el ingrediente
const
removeBtn
=
document
.
createElement
(
'button'
);
removeBtn
.
classList
.
add
(
'btn'
,
'btn-danger'
,
'btn-sm'
);
removeBtn
.
textContent
=
'x'
;
removeBtn
.
addEventListener
(
'click'
,
function
()
{
removeIngredient
(
ingredient
);
});
ingredientElement
.
appendChild
(
removeBtn
);
selectedIngredients
.
appendChild
(
ingredientElement
);
const
ingredientElement
=
document
.
createElement
(
'div'
);
ingredientElement
.
classList
.
add
(
'selected-ingredient'
);
ingredientElement
.
setAttribute
(
'data-ingredient-id'
,
ingredient
.
id
);
// Crear el elemento de imagen para el icono del ingrediente
const
iconElement
=
document
.
createElement
(
'img'
);
iconElement
.
classList
.
add
(
'ingredient-icon'
);
iconElement
.
src
=
'../imagenes/ingredientes/'
+
ingredient
.
icon
;
ingredientElement
.
appendChild
(
iconElement
);
// Agregar el nombre del ingrediente y la cantidad
const
ingredientNameAndQuantity
=
document
.
createElement
(
'span'
);
ingredientNameAndQuantity
.
textContent
=
`
${
ingredient
.
name
}
(
${
ingredient
.
quantity
}
)`
;
ingredientNameAndQuantity
.
classList
.
add
(
'ingredient-amount'
);
ingredientElement
.
appendChild
(
ingredientNameAndQuantity
);
// Agregar el botón para eliminar el ingrediente
const
removeBtn
=
document
.
createElement
(
'button'
);
removeBtn
.
classList
.
add
(
'btn'
,
'btn-danger'
,
'btn-sm'
);
removeBtn
.
textContent
=
'x'
;
removeBtn
.
addEventListener
(
'click'
,
function
()
{
removeIngredient
(
ingredient
);
});
ingredientElement
.
appendChild
(
removeBtn
);
selectedIngredients
.
appendChild
(
ingredientElement
);
});
}
}
...
...
@@ -154,43 +154,43 @@ ingredientSearch.addEventListener('input', function (event) {
var
inputPhoto
=
document
.
getElementById
(
'photo'
);
var
imageUploadContainer
=
document
.
querySelector
(
'.image-upload-container'
);
inputPhoto
.
addEventListener
(
'change'
,
function
(
event
)
{
inputPhoto
.
addEventListener
(
'change'
,
function
(
event
)
{
displayImagePreview
(
event
.
target
.
files
[
0
]);
});
imageUploadContainer
.
addEventListener
(
'dragover'
,
function
(
event
)
{
});
imageUploadContainer
.
addEventListener
(
'dragover'
,
function
(
event
)
{
event
.
preventDefault
();
event
.
stopPropagation
();
event
.
dataTransfer
.
dropEffect
=
'copy'
;
});
imageUploadContainer
.
addEventListener
(
'drop'
,
function
(
event
)
{
});
imageUploadContainer
.
addEventListener
(
'drop'
,
function
(
event
)
{
event
.
preventDefault
();
event
.
stopPropagation
();
if
(
event
.
dataTransfer
.
files
.
length
>
0
)
{
displayImagePreview
(
event
.
dataTransfer
.
files
[
0
]);
inputPhoto
.
files
=
event
.
dataTransfer
.
files
;
displayImagePreview
(
event
.
dataTransfer
.
files
[
0
]);
inputPhoto
.
files
=
event
.
dataTransfer
.
files
;
}
});
function
displayImagePreview
(
file
)
{
});
function
displayImagePreview
(
file
)
{
var
reader
=
new
FileReader
();
reader
.
onload
=
function
()
{
var
output
=
document
.
getElementById
(
'image-preview'
);
output
.
src
=
reader
.
result
;
output
.
style
.
display
=
'block'
;
reader
.
onload
=
function
()
{
var
output
=
document
.
getElementById
(
'image-preview'
);
output
.
src
=
reader
.
result
;
output
.
style
.
display
=
'block'
;
}
reader
.
readAsDataURL
(
file
);
}
}
document
.
getElementById
(
'photo'
).
addEventListener
(
'change'
,
function
(
event
)
{
document
.
getElementById
(
'photo'
).
addEventListener
(
'change'
,
function
(
event
)
{
var
reader
=
new
FileReader
();
reader
.
onload
=
function
()
{
var
output
=
document
.
getElementById
(
'image-preview'
);
output
.
src
=
reader
.
result
;
output
.
style
.
display
=
'block'
;
reader
.
onload
=
function
()
{
var
output
=
document
.
getElementById
(
'image-preview'
);
output
.
src
=
reader
.
result
;
output
.
style
.
display
=
'block'
;
}
reader
.
readAsDataURL
(
event
.
target
.
files
[
0
]);
});
});
public/js/main.js
View file @
b09851d8
/**
* Template Name: NiceAdmin
* Updated: Mar 09 2023 with Bootstrap v5.2.3
* Template URL: https://bootstrapmade.com/nice-admin-bootstrap-admin-html-template/
* Author: BootstrapMade.com
* License: https://bootstrapmade.com/license/
*/
(
function
()
{
"use strict"
;
/**
* Easy selector helper function
*/
const
select
=
(
el
,
all
=
false
)
=>
{
el
=
el
.
trim
()
if
(
all
)
{
return
[...
document
.
querySelectorAll
(
el
)]
(
function
()
{
const
recipesSearch
=
document
.
querySelector
(
'#search-query'
);
function
search_recipe
(
query
)
{
fetch
(
'/search_recipe'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/x-www-form-urlencoded'
,
'X-Requested-With'
:
'XMLHttpRequest'
},
body
:
'query='
+
encodeURIComponent
(
query
)
})
.
then
((
response
)
=>
response
.
json
())
.
then
((
searchResults
)
=>
{
// Limpiar la lista de recetas coincidentes anterior
const
recipeList
=
document
.
querySelector
(
'#recipe_list'
);
recipeList
.
innerHTML
=
''
;
// Agregar recetas coincidentes a la lista desplegable
searchResults
.
forEach
((
recipe
)
=>
{
const
listItem
=
document
.
createElement
(
'li'
);
listItem
.
classList
.
add
(
'recipe-item'
,
'd-flex'
,
'align-items-center'
,
'p-2'
,
'mb-1'
,
'bg-light'
,
'rounded'
);
const
nameElement
=
document
.
createElement
(
'span'
);
nameElement
.
textContent
=
recipe
.
name
;
nameElement
.
classList
.
add
(
'recipe-name'
,
'flex-grow-1'
);
listItem
.
appendChild
(
nameElement
);
listItem
.
setAttribute
(
'data-id'
,
recipe
.
id
);
listItem
.
setAttribute
(
'title'
,
'Haz clic para seleccionar '
+
recipe
.
name
);
listItem
.
setAttribute
(
'href'
,
'/recipe/'
+
recipe
.
id
);
listItem
.
addEventListener
(
'click'
,
function
()
{
window
.
location
.
href
=
this
.
getAttribute
(
'href'
);
});
recipeList
.
appendChild
(
listItem
);
});
});
}
// Agregar evento para ir a una receta cuando se seleccione
recipesSearch
.
addEventListener
(
'input'
,
function
(
event
)
{
// Llamar a la función search_recipe para buscar y mostrar recetas coincidentes
search_recipe
(
event
.
target
.
value
);
});
"use strict"
;
/**
* Easy selector helper function
*/
const
select
=
(
el
,
all
=
false
)
=>
{
el
=
el
.
trim
()
if
(
all
)
{
return
[...
document
.
querySelectorAll
(
el
)]
}
else
{
return
document
.
querySelector
(
el
)
}
}
/**
* Easy event listener function
*/
const
on
=
(
type
,
el
,
listener
,
all
=
false
)
=>
{
if
(
all
)
{
select
(
el
,
all
).
forEach
(
e
=>
e
.
addEventListener
(
type
,
listener
))
}
else
{
select
(
el
,
all
).
addEventListener
(
type
,
listener
)
}
}
/**
* Easy on scroll event listener
*/
const
onscroll
=
(
el
,
listener
)
=>
{
el
.
addEventListener
(
'scroll'
,
listener
)
}
/**
* Sidebar toggle
*/
if
(
select
(
'.toggle-sidebar-btn'
))
{
on
(
'click'
,
'.toggle-sidebar-btn'
,
function
(
e
)
{
select
(
'body'
).
classList
.
toggle
(
'toggle-sidebar'
)
})
}
/**
* Search bar toggle
*/
if
(
select
(
'.search-bar-toggle'
))
{
on
(
'click'
,
'.search-bar-toggle'
,
function
(
e
)
{
select
(
'.search-bar'
).
classList
.
toggle
(
'search-bar-show'
)
})
}
/**
* Navbar links active state on scroll
*/
let
navbarlinks
=
select
(
'#navbar .scrollto'
,
true
)
const
navbarlinksActive
=
()
=>
{
let
position
=
window
.
scrollY
+
200
navbarlinks
.
forEach
(
navbarlink
=>
{
if
(
!
navbarlink
.
hash
)
return
let
section
=
select
(
navbarlink
.
hash
)
if
(
!
section
)
return
if
(
position
>=
section
.
offsetTop
&&
position
<=
(
section
.
offsetTop
+
section
.
offsetHeight
))
{
navbarlink
.
classList
.
add
(
'active'
)
}
else
{
return
document
.
querySelector
(
el
)
navbarlink
.
classList
.
remove
(
'active'
)
}
}
/**
* Easy event listener function
*/
const
on
=
(
type
,
el
,
listener
,
all
=
false
)
=>
{
if
(
all
)
{
select
(
el
,
all
).
forEach
(
e
=>
e
.
addEventListener
(
type
,
listener
))
})
}
window
.
addEventListener
(
'load'
,
navbarlinksActive
)
onscroll
(
document
,
navbarlinksActive
)
/**
* Toggle .header-scrolled class to #header when page is scrolled
*/
let
selectHeader
=
select
(
'#header'
)
if
(
selectHeader
)
{
const
headerScrolled
=
()
=>
{
if
(
window
.
scrollY
>
100
)
{
selectHeader
.
classList
.
add
(
'header-scrolled'
)
}
else
{
select
(
el
,
all
).
addEventListener
(
type
,
listener
)
select
Header
.
classList
.
remove
(
'header-scrolled'
)
}
}
/**
* Easy on scroll event listener
*/
const
onscroll
=
(
el
,
listener
)
=>
{
el
.
addEventListener
(
'scroll'
,
listener
)
window
.
addEventListener
(
'load'
,
headerScrolled
)
onscroll
(
document
,
headerScrolled
)
}
/**
* Back to top button
*/
let
backtotop
=
select
(
'.back-to-top'
)
if
(
backtotop
)
{
const
toggleBacktotop
=
()
=>
{
if
(
window
.
scrollY
>
100
)
{
backtotop
.
classList
.
add
(
'active'
)
}
else
{
backtotop
.
classList
.
remove
(
'active'
)
}
}
/**
* Sidebar toggle
*/
if
(
select
(
'.toggle-sidebar-btn'
))
{
on
(
'click'
,
'.toggle-sidebar-btn'
,
function
(
e
)
{
select
(
'body'
).
classList
.
toggle
(
'toggle-sidebar'
)
})
window
.
addEventListener
(
'load'
,
toggleBacktotop
)
onscroll
(
document
,
toggleBacktotop
)
}
/**
* Initiate tooltips
*/
var
tooltipTriggerList
=
[].
slice
.
call
(
document
.
querySelectorAll
(
'[data-bs-toggle="tooltip"]'
))
var
tooltipList
=
tooltipTriggerList
.
map
(
function
(
tooltipTriggerEl
)
{
return
new
bootstrap
.
Tooltip
(
tooltipTriggerEl
)
})
/**
* Initiate quill editors
*/
if
(
select
(
'.quill-editor-default'
))
{
new
Quill
(
'.quill-editor-default'
,
{
theme
:
'snow'
});
}
if
(
select
(
'.quill-editor-bubble'
))
{
new
Quill
(
'.quill-editor-bubble'
,
{
theme
:
'bubble'
});
}
if
(
select
(
'.quill-editor-full'
))
{
new
Quill
(
".quill-editor-full"
,
{
modules
:
{
toolbar
:
[
[{
font
:
[]
},
{
size
:
[]
}],
[
"bold"
,
"italic"
,
"underline"
,
"strike"
],
[{
color
:
[]
},
{
background
:
[]
}
],
[{
script
:
"super"
},
{
script
:
"sub"
}
],
[{
list
:
"ordered"
},
{
list
:
"bullet"
},
{
indent
:
"-1"
},
{
indent
:
"+1"
}
],
[
"direction"
,
{
align
:
[]
}],
[
"link"
,
"image"
,
"video"
],
[
"clean"
]
]
},
theme
:
"snow"
});
}
/**
* Initiate TinyMCE Editor
*/
const
useDarkMode
=
window
.
matchMedia
(
'(prefers-color-scheme: dark)'
).
matches
;
const
isSmallScreen
=
window
.
matchMedia
(
'(max-width: 1023.5px)'
).
matches
;
tinymce
.
init
({
selector
:
'textarea.tinymce-editor'
,
plugins
:
'preview importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons'
,
editimage_cors_hosts
:
[
'picsum.photos'
],
menubar
:
'file edit view insert format tools table help'
,
toolbar
:
'undo redo | bold italic underline strikethrough | fontfamily fontsize blocks | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | forecolor backcolor removeformat | pagebreak | charmap emoticons | fullscreen preview save print | insertfile image media template link anchor codesample | ltr rtl'
,
toolbar_sticky
:
true
,
toolbar_sticky_offset
:
isSmallScreen
?
102
:
108
,
autosave_ask_before_unload
:
true
,
autosave_interval
:
'30s'
,
autosave_prefix
:
'{path}{query}-{id}-'
,
autosave_restore_when_empty
:
false
,
autosave_retention
:
'2m'
,
image_advtab
:
true
,
link_list
:
[{
title
:
'My page 1'
,
value
:
'https://www.tiny.cloud'
},
{
title
:
'My page 2'
,
value
:
'http://www.moxiecode.com'
}
/**
* Search bar toggle
*/
if
(
select
(
'.search-bar-toggle'
))
{
on
(
'click'
,
'.search-bar-toggle'
,
function
(
e
)
{
select
(
'.search-bar'
).
classList
.
toggle
(
'search-bar-show'
)
})
],
image_list
:
[{
title
:
'My page 1'
,
value
:
'https://www.tiny.cloud'
},
{
title
:
'My page 2'
,
value
:
'http://www.moxiecode.com'
}
/**
* Navbar links active state on scroll
*/
let
navbarlinks
=
select
(
'#navbar .scrollto'
,
true
)
const
navbarlinksActive
=
()
=>
{
let
position
=
window
.
scrollY
+
200
navbarlinks
.
forEach
(
navbarlink
=>
{
if
(
!
navbarlink
.
hash
)
return
let
section
=
select
(
navbarlink
.
hash
)
if
(
!
section
)
return
if
(
position
>=
section
.
offsetTop
&&
position
<=
(
section
.
offsetTop
+
section
.
offsetHeight
))
{
navbarlink
.
classList
.
add
(
'active'
)
}
else
{
navbarlink
.
classList
.
remove
(
'active'
)
}
})
],
image_class_list
:
[{
title
:
'None'
,
value
:
''
},
{
title
:
'Some class'
,
value
:
'class-name'
}
window
.
addEventListener
(
'load'
,
navbarlinksActive
)
onscroll
(
document
,
navbarlinksActive
)
/**
* Toggle .header-scrolled class to #header when page is scrolled
*/
let
selectHeader
=
select
(
'#header'
)
if
(
selectHeader
)
{
const
headerScrolled
=
()
=>
{
if
(
window
.
scrollY
>
100
)
{
selectHeader
.
classList
.
add
(
'header-scrolled'
)
}
else
{
selectHeader
.
classList
.
remove
(
'header-scrolled'
)
}
],
importcss_append
:
true
,
file_picker_callback
:
(
callback
,
value
,
meta
)
=>
{
/* Provide file and text for the link dialog */
if
(
meta
.
filetype
===
'file'
)
{
callback
(
'https://www.google.com/logos/google.jpg'
,
{
text
:
'My text'
});
}
window
.
addEventListener
(
'load'
,
headerScrolled
)
onscroll
(
document
,
headerScrolled
)
}
/**
* Back to top button
*/
let
backtotop
=
select
(
'.back-to-top'
)
if
(
backtotop
)
{
const
toggleBacktotop
=
()
=>
{
if
(
window
.
scrollY
>
100
)
{
backtotop
.
classList
.
add
(
'active'
)
}
else
{
backtotop
.
classList
.
remove
(
'active'
)
}
/* Provide image and alt text for the image dialog */
if
(
meta
.
filetype
===
'image'
)
{
callback
(
'https://www.google.com/logos/google.jpg'
,
{
alt
:
'My alt text'
});
}
window
.
addEventListener
(
'load'
,
toggleBacktotop
)
onscroll
(
document
,
toggleBacktotop
)
/* Provide alternative source and posted for the media dialog */
if
(
meta
.
filetype
===
'media'
)
{
callback
(
'movie.mp4'
,
{
source2
:
'alt.ogg'
,
poster
:
'https://www.google.com/logos/google.jpg'
});
}
},
templates
:
[{
title
:
'New Table'
,
description
:
'creates a new table'
,
content
:
'<div class="mceTmpl"><table width="98%%" border="0" cellspacing="0" cellpadding="0"><tr><th scope="col"> </th><th scope="col"> </th></tr><tr><td> </td><td> </td></tr></table></div>'
},
{
title
:
'Starting my story'
,
description
:
'A cure for writers block'
,
content
:
'Once upon a time...'
},
{
title
:
'New list with dates'
,
description
:
'New List with dates'
,
content
:
'<div class="mceTmpl"><span class="cdate">cdate</span><br><span class="mdate">mdate</span><h2>My List</h2><ul><li></li><li></li></ul></div>'
}
],
template_cdate_format
:
'[Date Created (CDATE): %m/%d/%Y : %H:%M:%S]'
,
template_mdate_format
:
'[Date Modified (MDATE): %m/%d/%Y : %H:%M:%S]'
,
height
:
600
,
image_caption
:
true
,
quickbars_selection_toolbar
:
'bold italic | quicklink h2 h3 blockquote quickimage quicktable'
,
noneditable_class
:
'mceNonEditable'
,
toolbar_mode
:
'sliding'
,
contextmenu
:
'link image table'
,
skin
:
useDarkMode
?
'oxide-dark'
:
'oxide'
,
content_css
:
useDarkMode
?
'dark'
:
'default'
,
content_style
:
'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
});
/**
* Initiate Bootstrap validation check
*/
var
needsValidation
=
document
.
querySelectorAll
(
'.needs-validation'
)
/**
* Initiate tooltips
*/
var
tooltipTriggerList
=
[].
slice
.
call
(
document
.
querySelectorAll
(
'[data-bs-toggle="tooltip"]'
))
var
tooltipList
=
tooltipTriggerList
.
map
(
function
(
tooltipTriggerEl
)
{
return
new
bootstrap
.
Tooltip
(
tooltipTriggerEl
)
})
/**
* Initiate quill editors
*/
if
(
select
(
'.quill-editor-default'
))
{
new
Quill
(
'.quill-editor-default'
,
{
theme
:
'snow'
});
}
if
(
select
(
'.quill-editor-bubble'
))
{
new
Quill
(
'.quill-editor-bubble'
,
{
theme
:
'bubble'
});
}
if
(
select
(
'.quill-editor-full'
))
{
new
Quill
(
".quill-editor-full"
,
{
modules
:
{
toolbar
:
[
[{
font
:
[]
},
{
size
:
[]
}],
[
"bold"
,
"italic"
,
"underline"
,
"strike"
],
[{
color
:
[]
},
{
background
:
[]
}
],
[{
script
:
"super"
},
{
script
:
"sub"
}
],
[{
list
:
"ordered"
},
{
list
:
"bullet"
},
{
indent
:
"-1"
},
{
indent
:
"+1"
}
],
[
"direction"
,
{
align
:
[]
}],
[
"link"
,
"image"
,
"video"
],
[
"clean"
]
]
},
theme
:
"snow"
});
}
/**
* Initiate TinyMCE Editor
*/
const
useDarkMode
=
window
.
matchMedia
(
'(prefers-color-scheme: dark)'
).
matches
;
const
isSmallScreen
=
window
.
matchMedia
(
'(max-width: 1023.5px)'
).
matches
;
tinymce
.
init
({
selector
:
'textarea.tinymce-editor'
,
plugins
:
'preview importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons'
,
editimage_cors_hosts
:
[
'picsum.photos'
],
menubar
:
'file edit view insert format tools table help'
,
toolbar
:
'undo redo | bold italic underline strikethrough | fontfamily fontsize blocks | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | forecolor backcolor removeformat | pagebreak | charmap emoticons | fullscreen preview save print | insertfile image media template link anchor codesample | ltr rtl'
,
toolbar_sticky
:
true
,
toolbar_sticky_offset
:
isSmallScreen
?
102
:
108
,
autosave_ask_before_unload
:
true
,
autosave_interval
:
'30s'
,
autosave_prefix
:
'{path}{query}-{id}-'
,
autosave_restore_when_empty
:
false
,
autosave_retention
:
'2m'
,
image_advtab
:
true
,
link_list
:
[{
title
:
'My page 1'
,
value
:
'https://www.tiny.cloud'
},
{
title
:
'My page 2'
,
value
:
'http://www.moxiecode.com'
}
],
image_list
:
[{
title
:
'My page 1'
,
value
:
'https://www.tiny.cloud'
},
{
title
:
'My page 2'
,
value
:
'http://www.moxiecode.com'
}
],
image_class_list
:
[{
title
:
'None'
,
value
:
''
},
{
title
:
'Some class'
,
value
:
'class-name'
Array
.
prototype
.
slice
.
call
(
needsValidation
)
.
forEach
(
function
(
form
)
{
form
.
addEventListener
(
'submit'
,
function
(
event
)
{
if
(
!
form
.
checkValidity
())
{
event
.
preventDefault
()
event
.
stopPropagation
()
}
],
importcss_append
:
true
,
file_picker_callback
:
(
callback
,
value
,
meta
)
=>
{
/* Provide file and text for the link dialog */
if
(
meta
.
filetype
===
'file'
)
{
callback
(
'https://www.google.com/logos/google.jpg'
,
{
text
:
'My text'
});
}
/* Provide image and alt text for the image dialog */
if
(
meta
.
filetype
===
'image'
)
{
callback
(
'https://www.google.com/logos/google.jpg'
,
{
alt
:
'My alt text'
});
}
/* Provide alternative source and posted for the media dialog */
if
(
meta
.
filetype
===
'media'
)
{
callback
(
'movie.mp4'
,
{
source2
:
'alt.ogg'
,
poster
:
'https://www.google.com/logos/google.jpg'
});
}
},
templates
:
[{
title
:
'New Table'
,
description
:
'creates a new table'
,
content
:
'<div class="mceTmpl"><table width="98%%" border="0" cellspacing="0" cellpadding="0"><tr><th scope="col"> </th><th scope="col"> </th></tr><tr><td> </td><td> </td></tr></table></div>'
},
{
title
:
'Starting my story'
,
description
:
'A cure for writers block'
,
content
:
'Once upon a time...'
},
{
title
:
'New list with dates'
,
description
:
'New List with dates'
,
content
:
'<div class="mceTmpl"><span class="cdate">cdate</span><br><span class="mdate">mdate</span><h2>My List</h2><ul><li></li><li></li></ul></div>'
}
],
template_cdate_format
:
'[Date Created (CDATE): %m/%d/%Y : %H:%M:%S]'
,
template_mdate_format
:
'[Date Modified (MDATE): %m/%d/%Y : %H:%M:%S]'
,
height
:
600
,
image_caption
:
true
,
quickbars_selection_toolbar
:
'bold italic | quicklink h2 h3 blockquote quickimage quicktable'
,
noneditable_class
:
'mceNonEditable'
,
toolbar_mode
:
'sliding'
,
contextmenu
:
'link image table'
,
skin
:
useDarkMode
?
'oxide-dark'
:
'oxide'
,
content_css
:
useDarkMode
?
'dark'
:
'default'
,
content_style
:
'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
});
/**
* Initiate Bootstrap validation check
*/
var
needsValidation
=
document
.
querySelectorAll
(
'.needs-validation'
)
Array
.
prototype
.
slice
.
call
(
needsValidation
)
.
forEach
(
function
(
form
)
{
form
.
addEventListener
(
'submit'
,
function
(
event
)
{
if
(
!
form
.
checkValidity
())
{
event
.
preventDefault
()
event
.
stopPropagation
()
}
form
.
classList
.
add
(
'was-validated'
)
},
false
)
})
/**
* Initiate Datatables
*/
const
datatables
=
select
(
'.datatable'
,
true
)
datatables
.
forEach
(
datatable
=>
{
new
simpleDatatables
.
DataTable
(
datatable
);
form
.
classList
.
add
(
'was-validated'
)
},
false
)
})
/**
* Autoresize echart charts
*/
const
mainContainer
=
select
(
'#main'
);
if
(
mainContainer
)
{
setTimeout
(()
=>
{
new
ResizeObserver
(
function
()
{
select
(
'.echart'
,
true
).
forEach
(
getEchart
=>
{
echarts
.
getInstanceByDom
(
getEchart
).
resize
();
})
}).
observe
(
mainContainer
);
},
200
);
}
/**
* Initiate Datatables
*/
const
datatables
=
select
(
'.datatable'
,
true
)
datatables
.
forEach
(
datatable
=>
{
new
simpleDatatables
.
DataTable
(
datatable
);
})
/**
* Autoresize echart charts
*/
const
mainContainer
=
select
(
'#main'
);
if
(
mainContainer
)
{
setTimeout
(()
=>
{
new
ResizeObserver
(
function
()
{
select
(
'.echart'
,
true
).
forEach
(
getEchart
=>
{
echarts
.
getInstanceByDom
(
getEchart
).
resize
();
})
}).
observe
(
mainContainer
);
},
200
);
}
/*
function search_recipe(query) {
if (query.trim() === '') {
document.querySelector('#recipe_dropdown').style.display = 'none';
return;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/search_recipe', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
var searchResults = JSON.parse(xhr.responseText);
const recipeList = document.querySelector('#recipe_list');
recipeList.innerHTML = '';
if (searchResults.length > 0) {
document.querySelector('#recipe_dropdown').style.display = 'block';
} else {
document.querySelector('#recipe_dropdown').style.display = 'none';
}
searchResults.forEach((recipe) => {
const listItem = document.createElement('li');
listItem.classList.add('recipe-item');
const nameElement = document.createElement('span');
nameElement.textContent = recipe.name;
listItem.appendChild(nameElement);
recipeList.appendChild(listItem);
});
} catch (error) {
console.error('Error parsing JSON response:', error);
}
} else if (xhr.readyState === 4) {
console.error('Error in request:', xhr.status, xhr.statusText);
}
};
xhr.send('query=' + encodeURIComponent(query));
}
document.addEventListener('click', function (event) {
if (!event.target.closest('.search-bar')) {
document.querySelector('#recipe_dropdown').style.display = 'none';
}
});
*/
function
search_recipe
(
query
)
{
fetch
(
'/search_recipe'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/x-www-form-urlencoded'
,
'X-Requested-With'
:
'XMLHttpRequest'
// Añadir esta línea
},
body
:
'query='
+
encodeURIComponent
(
query
)
})
.
then
((
response
)
=>
response
.
json
())
.
then
((
searchResults
)
=>
{
// Limpiar la lista de ingredientes coincidentes anterior
const
recipeList
=
document
.
querySelector
(
'#recipe_dropdown'
);
recipeList
.
innerHTML
=
''
;
// Agregar ingredientes coincidentes a la lista desplegable
searchResults
.
forEach
((
ingredient
)
=>
{
const
listItem
=
document
.
createElement
(
'li'
);
listItem
.
classList
.
add
(
'recipe-item'
,
'd-flex'
,
'align-items-center'
,
'p-2'
,
'mb-1'
,
'bg-light'
,
'rounded'
);
const
nameElement
=
document
.
createElement
(
'span'
);
nameElement
.
textContent
=
ingredient
.
name
;
nameElement
.
classList
.
add
(
'recipe-name'
,
'flex-grow-1'
);
listItem
.
appendChild
(
nameElement
);
listItem
.
setAttribute
(
'data-id'
,
recipes
.
id
);
listItem
.
setAttribute
(
'title'
,
'Haz clic para seleccionar '
+
recipes
.
name
);
// Añade información adicional al ingrediente
recipeList
.
appendChild
(
listItem
);
});
});
}
// Agregar evento para agregar ingredientes cuando se presiona Enter en el campo de búsqueda
ingredientSearch
.
addEventListener
(
'search'
,
function
(
event
)
{
// Llamar a la función searchIngredients para buscar y mostrar ingredientes coincidentes
search_recipe
(
event
.
target
.
value
);
});
})();
\ No newline at end of file
/*
function search_recipe(query) {
if (query.trim() === '') {
document.querySelector('#recipe_dropdown').style.display = 'none';
return;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/search_recipe', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
var searchResults = JSON.parse(xhr.responseText);
const recipeList = document.querySelector('#recipe_list');
recipeList.innerHTML = '';
if (searchResults.length > 0) {
document.querySelector('#recipe_dropdown').style.display = 'block';
} else {
document.querySelector('#recipe_dropdown').style.display = 'none';
}
searchResults.forEach((recipe) => {
const listItem = document.createElement('li');
listItem.classList.add('recipe-item');
const nameElement = document.createElement('span');
nameElement.textContent = recipe.name;
listItem.appendChild(nameElement);
recipeList.appendChild(listItem);
});
} catch (error) {
console.error('Error parsing JSON response:', error);
}
} else if (xhr.readyState === 4) {
console.error('Error in request:', xhr.status, xhr.statusText);
}
};
xhr.send('query=' + encodeURIComponent(query));
}
document.addEventListener('click', function (event) {
if (!event.target.closest('.search-bar')) {
document.querySelector('#recipe_dropdown').style.display = 'none';
}
});
*/
})();
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment