From 4d323b4de5ef0fc6a57582e395bf447612115600 Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Fri, 21 Feb 2025 13:56:50 +0000
Subject: [PATCH 01/25] First Commit

---
 Pipfile.lock                         | 654 +++++++++++++++------------
 migrations/README                    |   1 +
 migrations/alembic.ini               |  50 ++
 migrations/env.py                    | 113 +++++
 migrations/script.py.mako            |  24 +
 migrations/versions/22b5bf5541c4_.py |  35 ++
 src/front/img/microphone.jpg         | Bin 0 -> 112253 bytes
 src/front/js/layout.js               |  53 ++-
 src/front/js/pages/login.js          |  76 ++++
 src/front/styles/home.css            |  10 +-
 src/front/styles/login.css           |   7 +
 11 files changed, 707 insertions(+), 316 deletions(-)
 create mode 100644 migrations/README
 create mode 100644 migrations/alembic.ini
 create mode 100644 migrations/env.py
 create mode 100644 migrations/script.py.mako
 create mode 100644 migrations/versions/22b5bf5541c4_.py
 create mode 100644 src/front/img/microphone.jpg
 create mode 100644 src/front/js/pages/login.js
 create mode 100644 src/front/styles/login.css

diff --git a/Pipfile.lock b/Pipfile.lock
index a391864e9d..508225b0a1 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "74f92d76f687bb774828613a3a513123fe2ffdb429b95b351d29721dddfd3fb8"
+            "sha256": "4f0e9a772f04b621ff0313b7ecfa468af1526aa27df8bfcacac6955d499d352d"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -18,73 +18,91 @@
     "default": {
         "alembic": {
             "hashes": [
-                "sha256:6880dec4f28dd7bd999d2ed13fbe7c9d4337700a44d11a524c0ce0c59aaf0dbd",
-                "sha256:e8a6ff9f3b1887e1fed68bfb8fb9a000d8f61c21bdcc85b67bb9f87fcbc4fce3"
+                "sha256:1acdd7a3a478e208b0503cd73614d5e4c6efafa4e73518bb60e4f2846a37b1c5",
+                "sha256:496e888245a53adf1498fcab31713a469c65836f8de76e01399aa1c3e90dd213"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==1.9.2"
+            "markers": "python_version >= '3.8'",
+            "version": "==1.14.1"
+        },
+        "blinker": {
+            "hashes": [
+                "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf",
+                "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"
+            ],
+            "markers": "python_version >= '3.9'",
+            "version": "==1.9.0"
         },
         "certifi": {
             "hashes": [
-                "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
-                "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
+                "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651",
+                "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"
             ],
             "markers": "python_version >= '3.6'",
-            "version": "==2022.12.7"
+            "version": "==2025.1.31"
         },
         "click": {
             "hashes": [
-                "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
-                "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
+                "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2",
+                "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==8.1.3"
+            "version": "==8.1.8"
         },
         "cloudinary": {
             "hashes": [
-                "sha256:f52a1f5eb2c6820f13aa01c109caa5937ad3fd6caf5967817d0ef6c113403afc"
+                "sha256:ba223705409b2aaddd5196c2184d65f50a83dffcba3b94f3727658ff6a0172a3",
+                "sha256:e4191b470c5bae55542b64e0a78659af42971880294456dca480bc974fa9280a"
             ],
             "index": "pypi",
-            "version": "==1.31.0"
+            "version": "==1.42.2"
         },
         "flask": {
             "hashes": [
-                "sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b",
-                "sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526"
+                "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac",
+                "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136"
             ],
             "index": "pypi",
-            "version": "==2.2.2"
+            "version": "==3.1.0"
         },
         "flask-admin": {
             "hashes": [
-                "sha256:424ffc79b7b0dfff051555686ea12e86e48dffacac14beaa319fb4502ac40988"
+                "sha256:24cae2af832b6a611a01d7dc35f42d266c1d6c75a426b869d8cb241b78233369",
+                "sha256:fd8190f1ec3355913a22739c46ed3623f1d82b8112cde324c60a6fc9b21c9406"
             ],
             "index": "pypi",
-            "version": "==1.6.0"
+            "version": "==1.6.1"
         },
         "flask-cors": {
             "hashes": [
-                "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438",
-                "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"
+                "sha256:5aadb4b950c4e93745034594d9f3ea6591f734bb3662e16e255ffbf5e89c88ef",
+                "sha256:b9e307d082a9261c100d8fb0ba909eec6a228ed1b60a8315fd85f783d61910bc"
+            ],
+            "index": "pypi",
+            "version": "==5.0.0"
+        },
+        "flask-jwt-extended": {
+            "hashes": [
+                "sha256:63a28fc9731bcc6c4b8815b6f954b5904caa534fc2ae9b93b1d3ef12930dca95",
+                "sha256:9215d05a9413d3855764bcd67035e75819d23af2fafb6b55197eb5a3313fdfb2"
             ],
             "index": "pypi",
-            "version": "==3.0.10"
+            "version": "==4.6.0"
         },
         "flask-migrate": {
             "hashes": [
-                "sha256:8662a9dd391ce36deeaf3265987319c20fdb4c8a45306a32ba4f8224459abed4",
-                "sha256:a0062c8d3f32de02847086b46cfc389412f78c71c89a619ebd7097e89d72ea4b"
+                "sha256:1a336b06eb2c3ace005f5f2ded8641d534c18798d64061f6ff11f79e1434126d",
+                "sha256:24d8051af161782e0743af1b04a152d007bad9772b2bca67b7ec1e8ceeb3910d"
             ],
             "index": "pypi",
-            "version": "==4.0.3"
+            "version": "==4.1.0"
         },
         "flask-sqlalchemy": {
             "hashes": [
-                "sha256:2764335f3c9d7ebdc9ed6044afaf98aae9fa50d7a074cef55dde307ec95903ec",
-                "sha256:add5750b2f9cd10512995261ee2aa23fab85bd5626061aa3c564b33bb4aa780a"
+                "sha256:c5765e58ca145401b52106c0f46178569243c5da25556be2c231ecc60867c5b1",
+                "sha256:cabb6600ddd819a9f859f36515bb1bd8e7dbf30206cc679d2b081dff9e383283"
             ],
             "index": "pypi",
-            "version": "==3.0.3"
+            "version": "==3.0.5"
         },
         "flask-swagger": {
             "hashes": [
@@ -96,304 +114,346 @@
         },
         "greenlet": {
             "hashes": [
-                "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a",
-                "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a",
-                "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43",
-                "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33",
-                "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8",
-                "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088",
-                "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca",
-                "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343",
-                "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645",
-                "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db",
-                "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df",
-                "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3",
-                "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86",
-                "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2",
-                "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a",
-                "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf",
-                "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7",
-                "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394",
-                "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40",
-                "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3",
-                "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6",
-                "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74",
-                "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0",
-                "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3",
-                "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91",
-                "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5",
-                "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9",
-                "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8",
-                "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b",
-                "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6",
-                "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb",
-                "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73",
-                "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b",
-                "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df",
-                "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9",
-                "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f",
-                "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0",
-                "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857",
-                "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a",
-                "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249",
-                "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30",
-                "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292",
-                "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b",
-                "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d",
-                "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b",
-                "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c",
-                "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca",
-                "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7",
-                "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75",
-                "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae",
-                "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b",
-                "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470",
-                "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564",
-                "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9",
-                "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099",
-                "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0",
-                "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5",
-                "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19",
-                "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1",
-                "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"
+                "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e",
+                "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7",
+                "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01",
+                "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1",
+                "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159",
+                "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563",
+                "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83",
+                "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9",
+                "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395",
+                "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa",
+                "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942",
+                "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1",
+                "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441",
+                "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22",
+                "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9",
+                "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0",
+                "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba",
+                "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3",
+                "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1",
+                "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6",
+                "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291",
+                "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39",
+                "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d",
+                "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467",
+                "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475",
+                "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef",
+                "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c",
+                "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511",
+                "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c",
+                "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822",
+                "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a",
+                "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8",
+                "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d",
+                "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01",
+                "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145",
+                "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80",
+                "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13",
+                "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e",
+                "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b",
+                "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1",
+                "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef",
+                "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc",
+                "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff",
+                "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120",
+                "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437",
+                "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd",
+                "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981",
+                "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36",
+                "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a",
+                "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798",
+                "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7",
+                "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761",
+                "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0",
+                "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e",
+                "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af",
+                "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa",
+                "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c",
+                "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42",
+                "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e",
+                "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81",
+                "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e",
+                "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617",
+                "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc",
+                "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de",
+                "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111",
+                "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383",
+                "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70",
+                "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6",
+                "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4",
+                "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011",
+                "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803",
+                "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79",
+                "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f"
             ],
             "markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))",
-            "version": "==2.0.2"
+            "version": "==3.1.1"
         },
         "gunicorn": {
             "hashes": [
-                "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
-                "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
+                "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d",
+                "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"
             ],
             "index": "pypi",
-            "version": "==20.1.0"
+            "version": "==23.0.0"
         },
         "itsdangerous": {
             "hashes": [
-                "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
-                "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
+                "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
+                "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==2.1.2"
+            "markers": "python_version >= '3.8'",
+            "version": "==2.2.0"
         },
         "jinja2": {
             "hashes": [
-                "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
-                "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
+                "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb",
+                "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==3.1.2"
+            "version": "==3.1.5"
         },
         "mako": {
             "hashes": [
-                "sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818",
-                "sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34"
+                "sha256:95920acccb578427a9aa38e37a186b1e43156c87260d7ba18ca63aa4c7cbd3a1",
+                "sha256:b5d65ff3462870feec922dbccf38f6efb44e5714d7b593a656be86663d8600ac"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==1.2.4"
+            "markers": "python_version >= '3.8'",
+            "version": "==1.3.9"
         },
         "markupsafe": {
             "hashes": [
-                "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed",
-                "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc",
-                "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2",
-                "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460",
-                "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7",
-                "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0",
-                "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1",
-                "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa",
-                "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03",
-                "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323",
-                "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65",
-                "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013",
-                "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036",
-                "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f",
-                "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4",
-                "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419",
-                "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2",
-                "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619",
-                "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a",
-                "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a",
-                "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd",
-                "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7",
-                "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666",
-                "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65",
-                "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859",
-                "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625",
-                "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff",
-                "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156",
-                "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd",
-                "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba",
-                "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f",
-                "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1",
-                "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094",
-                "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a",
-                "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513",
-                "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed",
-                "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d",
-                "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3",
-                "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147",
-                "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c",
-                "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603",
-                "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601",
-                "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a",
-                "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1",
-                "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d",
-                "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3",
-                "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54",
-                "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2",
-                "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6",
-                "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"
+                "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4",
+                "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30",
+                "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0",
+                "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9",
+                "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396",
+                "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13",
+                "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028",
+                "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca",
+                "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557",
+                "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832",
+                "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0",
+                "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b",
+                "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579",
+                "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a",
+                "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c",
+                "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff",
+                "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c",
+                "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22",
+                "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094",
+                "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb",
+                "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e",
+                "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5",
+                "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a",
+                "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d",
+                "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a",
+                "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b",
+                "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8",
+                "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225",
+                "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c",
+                "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144",
+                "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f",
+                "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87",
+                "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d",
+                "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93",
+                "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf",
+                "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158",
+                "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84",
+                "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb",
+                "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48",
+                "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171",
+                "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c",
+                "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6",
+                "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd",
+                "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d",
+                "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1",
+                "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d",
+                "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca",
+                "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a",
+                "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29",
+                "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe",
+                "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798",
+                "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c",
+                "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8",
+                "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f",
+                "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f",
+                "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a",
+                "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178",
+                "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0",
+                "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79",
+                "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430",
+                "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==2.1.2"
+            "markers": "python_version >= '3.9'",
+            "version": "==3.0.2"
+        },
+        "packaging": {
+            "hashes": [
+                "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
+                "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==24.2"
         },
         "psycopg2-binary": {
             "hashes": [
-                "sha256:00475004e5ed3e3bf5e056d66e5dcdf41a0dc62efcd57997acd9135c40a08a50",
-                "sha256:01ad49d68dd8c5362e4bfb4158f2896dc6e0c02e87b8a3770fc003459f1a4425",
-                "sha256:024030b13bdcbd53d8a93891a2cf07719715724fc9fee40243f3bd78b4264b8f",
-                "sha256:02551647542f2bf89073d129c73c05a25c372fc0a49aa50e0de65c3c143d8bd0",
-                "sha256:043a9fd45a03858ff72364b4b75090679bd875ee44df9c0613dc862ca6b98460",
-                "sha256:05b3d479425e047c848b9782cd7aac9c6727ce23181eb9647baf64ffdfc3da41",
-                "sha256:0775d6252ccb22b15da3b5d7adbbf8cfe284916b14b6dc0ff503a23edb01ee85",
-                "sha256:1764546ffeaed4f9428707be61d68972eb5ede81239b46a45843e0071104d0dd",
-                "sha256:1e491e6489a6cb1d079df8eaa15957c277fdedb102b6a68cfbf40c4994412fd0",
-                "sha256:212757ffcecb3e1a5338d4e6761bf9c04f750e7d027117e74aa3cd8a75bb6fbd",
-                "sha256:215d6bf7e66732a514f47614f828d8c0aaac9a648c46a831955cb103473c7147",
-                "sha256:25382c7d174c679ce6927c16b6fbb68b10e56ee44b1acb40671e02d29f2fce7c",
-                "sha256:2abccab84d057723d2ca8f99ff7b619285d40da6814d50366f61f0fc385c3903",
-                "sha256:2d964eb24c8b021623df1c93c626671420c6efadbdb8655cb2bd5e0c6fa422ba",
-                "sha256:2ec46ed947801652c9643e0b1dc334cfb2781232e375ba97312c2fc256597632",
-                "sha256:2ef892cabdccefe577088a79580301f09f2a713eb239f4f9f62b2b29cafb0577",
-                "sha256:33e632d0885b95a8b97165899006c40e9ecdc634a529dca7b991eb7de4ece41c",
-                "sha256:3520d7af1ebc838cc6084a3281145d5cd5bdd43fdef139e6db5af01b92596cb7",
-                "sha256:3d790f84201c3698d1bfb404c917f36e40531577a6dda02e45ba29b64d539867",
-                "sha256:3fc33295cfccad697a97a76dec3f1e94ad848b7b163c3228c1636977966b51e2",
-                "sha256:422e3d43b47ac20141bc84b3d342eead8d8099a62881a501e97d15f6addabfe9",
-                "sha256:426c2ae999135d64e6a18849a7d1ad0e1bd007277e4a8f4752eaa40a96b550ff",
-                "sha256:46512486be6fbceef51d7660dec017394ba3e170299d1dc30928cbedebbf103a",
-                "sha256:46850a640df62ae940e34a163f72e26aca1f88e2da79148e1862faaac985c302",
-                "sha256:484405b883630f3e74ed32041a87456c5e0e63a8e3429aa93e8714c366d62bd1",
-                "sha256:4e7904d1920c0c89105c0517dc7e3f5c20fb4e56ba9cdef13048db76947f1d79",
-                "sha256:56b2957a145f816726b109ee3d4e6822c23f919a7d91af5a94593723ed667835",
-                "sha256:5c6527c8efa5226a9e787507652dd5ba97b62d29b53c371a85cd13f957fe4d42",
-                "sha256:5cbc554ba47ecca8cd3396ddaca85e1ecfe3e48dd57dc5e415e59551affe568e",
-                "sha256:5d28ecdf191db558d0c07d0f16524ee9d67896edf2b7990eea800abeb23ebd61",
-                "sha256:5fc447058d083b8c6ac076fc26b446d44f0145308465d745fba93a28c14c9e32",
-                "sha256:63e318dbe52709ed10d516a356f22a635e07a2e34c68145484ed96a19b0c4c68",
-                "sha256:68d81a2fe184030aa0c5c11e518292e15d342a667184d91e30644c9d533e53e1",
-                "sha256:6e63814ec71db9bdb42905c925639f319c80e7909fb76c3b84edc79dadef8d60",
-                "sha256:6f8a9bcab7b6db2e3dbf65b214dfc795b4c6b3bb3af922901b6a67f7cb47d5f8",
-                "sha256:70831e03bd53702c941da1a1ad36c17d825a24fbb26857b40913d58df82ec18b",
-                "sha256:74eddec4537ab1f701a1647214734bc52cee2794df748f6ae5908e00771f180a",
-                "sha256:7b3751857da3e224f5629400736a7b11e940b5da5f95fa631d86219a1beaafec",
-                "sha256:7cf1d44e710ca3a9ce952bda2855830fe9f9017ed6259e01fcd71ea6287565f5",
-                "sha256:7d07f552d1e412f4b4e64ce386d4c777a41da3b33f7098b6219012ba534fb2c2",
-                "sha256:7d88db096fa19d94f433420eaaf9f3c45382da2dd014b93e4bf3215639047c16",
-                "sha256:7ee3095d02d6f38bd7d9a5358fcc9ea78fcdb7176921528dd709cc63f40184f5",
-                "sha256:902844f9c4fb19b17dfa84d9e2ca053d4a4ba265723d62ea5c9c26b38e0aa1e6",
-                "sha256:937880290775033a743f4836aa253087b85e62784b63fd099ee725d567a48aa1",
-                "sha256:95076399ec3b27a8f7fa1cc9a83417b1c920d55cf7a97f718a94efbb96c7f503",
-                "sha256:9c38d3869238e9d3409239bc05bc27d6b7c99c2a460ea337d2814b35fb4fea1b",
-                "sha256:9e32cedc389bcb76d9f24ea8a012b3cb8385ee362ea437e1d012ffaed106c17d",
-                "sha256:9ffdc51001136b699f9563b1c74cc1f8c07f66ef7219beb6417a4c8aaa896c28",
-                "sha256:a0adef094c49f242122bb145c3c8af442070dc0e4312db17e49058c1702606d4",
-                "sha256:a36a0e791805aa136e9cbd0ffa040d09adec8610453ee8a753f23481a0057af5",
-                "sha256:a7e518a0911c50f60313cb9e74a169a65b5d293770db4770ebf004245f24b5c5",
-                "sha256:af0516e1711995cb08dc19bbd05bec7dbdebf4185f68870595156718d237df3e",
-                "sha256:b8104f709590fff72af801e916817560dbe1698028cd0afe5a52d75ceb1fce5f",
-                "sha256:b911dfb727e247340d36ae20c4b9259e4a64013ab9888ccb3cbba69b77fd9636",
-                "sha256:b9a794cef1d9c1772b94a72eec6da144c18e18041d294a9ab47669bc77a80c1d",
-                "sha256:b9c33d4aef08dfecbd1736ceab8b7b3c4358bf10a0121483e5cd60d3d308cc64",
-                "sha256:b9d38a4656e4e715d637abdf7296e98d6267df0cc0a8e9a016f8ba07e4aa3eeb",
-                "sha256:bcda1c84a1c533c528356da5490d464a139b6e84eb77cc0b432e38c5c6dd7882",
-                "sha256:bef7e3f9dc6f0c13afdd671008534be5744e0e682fb851584c8c3a025ec09720",
-                "sha256:c15ba5982c177bc4b23a7940c7e4394197e2d6a424a2d282e7c236b66da6d896",
-                "sha256:c5254cbd4f4855e11cebf678c1a848a3042d455a22a4ce61349c36aafd4c2267",
-                "sha256:c5682a45df7d9642eff590abc73157c887a68f016df0a8ad722dcc0f888f56d7",
-                "sha256:c5e65c6ac0ae4bf5bef1667029f81010b6017795dcb817ba5c7b8a8d61fab76f",
-                "sha256:d4c7b3a31502184e856df1f7bbb2c3735a05a8ce0ade34c5277e1577738a5c91",
-                "sha256:d892bfa1d023c3781a3cab8dd5af76b626c483484d782e8bd047c180db590e4c",
-                "sha256:dbc332beaf8492b5731229a881807cd7b91b50dbbbaf7fe2faf46942eda64a24",
-                "sha256:dc85b3777068ed30aff8242be2813038a929f2084f69e43ef869daddae50f6ee",
-                "sha256:e59137cdb970249ae60be2a49774c6dfb015bd0403f05af1fe61862e9626642d",
-                "sha256:e67b3c26e9b6d37b370c83aa790bbc121775c57bfb096c2e77eacca25fd0233b",
-                "sha256:e72c91bda9880f097c8aa3601a2c0de6c708763ba8128006151f496ca9065935",
-                "sha256:f95b8aca2703d6a30249f83f4fe6a9abf2e627aa892a5caaab2267d56be7ab69"
+                "sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff",
+                "sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5",
+                "sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f",
+                "sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5",
+                "sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0",
+                "sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c",
+                "sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c",
+                "sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341",
+                "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f",
+                "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7",
+                "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d",
+                "sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007",
+                "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142",
+                "sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92",
+                "sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb",
+                "sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5",
+                "sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5",
+                "sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8",
+                "sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1",
+                "sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68",
+                "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73",
+                "sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1",
+                "sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53",
+                "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d",
+                "sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906",
+                "sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0",
+                "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2",
+                "sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a",
+                "sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b",
+                "sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44",
+                "sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648",
+                "sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7",
+                "sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f",
+                "sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa",
+                "sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697",
+                "sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d",
+                "sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b",
+                "sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526",
+                "sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4",
+                "sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287",
+                "sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e",
+                "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673",
+                "sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0",
+                "sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30",
+                "sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3",
+                "sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e",
+                "sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92",
+                "sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a",
+                "sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c",
+                "sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8",
+                "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909",
+                "sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47",
+                "sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864",
+                "sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc",
+                "sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00",
+                "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb",
+                "sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539",
+                "sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b",
+                "sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481",
+                "sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5",
+                "sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4",
+                "sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64",
+                "sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392",
+                "sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4",
+                "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1",
+                "sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1",
+                "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567",
+                "sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863"
             ],
             "index": "pypi",
-            "version": "==2.9.5"
+            "version": "==2.9.10"
         },
-        "python-dotenv": {
+        "pyjwt": {
             "hashes": [
-                "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49",
-                "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"
+                "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953",
+                "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"
             ],
-            "index": "pypi",
-            "version": "==0.21.1"
+            "markers": "python_version >= '3.9'",
+            "version": "==2.10.1"
         },
-        "pyyaml": {
+        "python-dotenv": {
             "hashes": [
-                "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf",
-                "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293",
-                "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b",
-                "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57",
-                "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b",
-                "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4",
-                "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07",
-                "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba",
-                "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9",
-                "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287",
-                "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513",
-                "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0",
-                "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782",
-                "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0",
-                "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92",
-                "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f",
-                "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2",
-                "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc",
-                "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1",
-                "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c",
-                "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86",
-                "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4",
-                "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c",
-                "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34",
-                "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b",
-                "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d",
-                "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c",
-                "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb",
-                "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7",
-                "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737",
-                "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3",
-                "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d",
-                "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358",
-                "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53",
-                "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78",
-                "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803",
-                "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a",
-                "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f",
-                "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174",
-                "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"
+                "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca",
+                "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==6.0"
+            "index": "pypi",
+            "version": "==1.0.1"
         },
-        "setuptools": {
+        "pyyaml": {
             "hashes": [
-                "sha256:a7687c12b444eaac951ea87a9627c4f904ac757e7abdc5aac32833234af90378",
-                "sha256:e261cdf010c11a41cb5cb5f1bf3338a7433832029f559a6a7614bd42a967c300"
+                "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff",
+                "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48",
+                "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086",
+                "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e",
+                "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133",
+                "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5",
+                "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484",
+                "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee",
+                "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5",
+                "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68",
+                "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a",
+                "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf",
+                "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99",
+                "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8",
+                "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85",
+                "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19",
+                "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc",
+                "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a",
+                "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1",
+                "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317",
+                "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c",
+                "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631",
+                "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d",
+                "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652",
+                "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5",
+                "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e",
+                "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b",
+                "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8",
+                "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476",
+                "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706",
+                "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563",
+                "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237",
+                "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b",
+                "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083",
+                "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180",
+                "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425",
+                "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e",
+                "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f",
+                "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725",
+                "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183",
+                "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab",
+                "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774",
+                "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725",
+                "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e",
+                "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5",
+                "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d",
+                "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290",
+                "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44",
+                "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed",
+                "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4",
+                "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba",
+                "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12",
+                "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==67.1.0"
+            "markers": "python_version >= '3.8'",
+            "version": "==6.0.2"
         },
         "six": {
             "hashes": [
-                "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
-                "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+                "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
+                "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
             ],
             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==1.16.0"
+            "version": "==1.17.0"
         },
         "sqlalchemy": {
             "hashes": [
@@ -444,35 +504,35 @@
         },
         "typing-extensions": {
             "hashes": [
-                "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa",
-                "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"
+                "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d",
+                "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"
             ],
             "index": "pypi",
-            "version": "==4.4.0"
+            "version": "==4.12.2"
         },
         "urllib3": {
             "hashes": [
-                "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72",
-                "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"
+                "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df",
+                "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
-            "version": "==1.26.14"
+            "markers": "python_version >= '3.9'",
+            "version": "==2.3.0"
         },
         "werkzeug": {
             "hashes": [
-                "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f",
-                "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5"
+                "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e",
+                "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==2.2.2"
+            "markers": "python_version >= '3.9'",
+            "version": "==3.1.3"
         },
         "wtforms": {
             "hashes": [
-                "sha256:6b351bbb12dd58af57ffef05bc78425d08d1914e0fd68ee14143b7ade023c5bc",
-                "sha256:837f2f0e0ca79481b92884962b914eba4e72b7a2daaf1f939c890ed0124b834b"
+                "sha256:bf831c042829c8cdbad74c27575098d541d039b1faa74c771545ecac916f2c07",
+                "sha256:f8d76180d7239c94c6322f7990ae1216dae3659b7aa1cee94b6318bdffb474b9"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==3.0.1"
+            "index": "pypi",
+            "version": "==3.1.2"
         }
     },
     "develop": {}
diff --git a/migrations/README b/migrations/README
new file mode 100644
index 0000000000..0e04844159
--- /dev/null
+++ b/migrations/README
@@ -0,0 +1 @@
+Single-database configuration for Flask.
diff --git a/migrations/alembic.ini b/migrations/alembic.ini
new file mode 100644
index 0000000000..ec9d45c26a
--- /dev/null
+++ b/migrations/alembic.ini
@@ -0,0 +1,50 @@
+# A generic, single database configuration.
+
+[alembic]
+# template used to generate migration files
+# file_template = %%(rev)s_%%(slug)s
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic,flask_migrate
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[logger_flask_migrate]
+level = INFO
+handlers =
+qualname = flask_migrate
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S
diff --git a/migrations/env.py b/migrations/env.py
new file mode 100644
index 0000000000..4c9709271b
--- /dev/null
+++ b/migrations/env.py
@@ -0,0 +1,113 @@
+import logging
+from logging.config import fileConfig
+
+from flask import current_app
+
+from alembic import context
+
+# this is the Alembic Config object, which provides
+# access to the values within the .ini file in use.
+config = context.config
+
+# Interpret the config file for Python logging.
+# This line sets up loggers basically.
+fileConfig(config.config_file_name)
+logger = logging.getLogger('alembic.env')
+
+
+def get_engine():
+    try:
+        # this works with Flask-SQLAlchemy<3 and Alchemical
+        return current_app.extensions['migrate'].db.get_engine()
+    except (TypeError, AttributeError):
+        # this works with Flask-SQLAlchemy>=3
+        return current_app.extensions['migrate'].db.engine
+
+
+def get_engine_url():
+    try:
+        return get_engine().url.render_as_string(hide_password=False).replace(
+            '%', '%%')
+    except AttributeError:
+        return str(get_engine().url).replace('%', '%%')
+
+
+# add your model's MetaData object here
+# for 'autogenerate' support
+# from myapp import mymodel
+# target_metadata = mymodel.Base.metadata
+config.set_main_option('sqlalchemy.url', get_engine_url())
+target_db = current_app.extensions['migrate'].db
+
+# other values from the config, defined by the needs of env.py,
+# can be acquired:
+# my_important_option = config.get_main_option("my_important_option")
+# ... etc.
+
+
+def get_metadata():
+    if hasattr(target_db, 'metadatas'):
+        return target_db.metadatas[None]
+    return target_db.metadata
+
+
+def run_migrations_offline():
+    """Run migrations in 'offline' mode.
+
+    This configures the context with just a URL
+    and not an Engine, though an Engine is acceptable
+    here as well.  By skipping the Engine creation
+    we don't even need a DBAPI to be available.
+
+    Calls to context.execute() here emit the given string to the
+    script output.
+
+    """
+    url = config.get_main_option("sqlalchemy.url")
+    context.configure(
+        url=url, target_metadata=get_metadata(), literal_binds=True
+    )
+
+    with context.begin_transaction():
+        context.run_migrations()
+
+
+def run_migrations_online():
+    """Run migrations in 'online' mode.
+
+    In this scenario we need to create an Engine
+    and associate a connection with the context.
+
+    """
+
+    # this callback is used to prevent an auto-migration from being generated
+    # when there are no changes to the schema
+    # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
+    def process_revision_directives(context, revision, directives):
+        if getattr(config.cmd_opts, 'autogenerate', False):
+            script = directives[0]
+            if script.upgrade_ops.is_empty():
+                directives[:] = []
+                logger.info('No changes in schema detected.')
+
+    conf_args = current_app.extensions['migrate'].configure_args
+    if conf_args.get("process_revision_directives") is None:
+        conf_args["process_revision_directives"] = process_revision_directives
+
+    connectable = get_engine()
+
+    with connectable.connect() as connection:
+        context.configure(
+            connection=connection,
+            target_metadata=get_metadata(),
+            **conf_args
+        )
+
+        with context.begin_transaction():
+            context.run_migrations()
+
+
+if context.is_offline_mode():
+    run_migrations_offline()
+else:
+    run_migrations_online()
diff --git a/migrations/script.py.mako b/migrations/script.py.mako
new file mode 100644
index 0000000000..2c0156303a
--- /dev/null
+++ b/migrations/script.py.mako
@@ -0,0 +1,24 @@
+"""${message}
+
+Revision ID: ${up_revision}
+Revises: ${down_revision | comma,n}
+Create Date: ${create_date}
+
+"""
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
+
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+branch_labels = ${repr(branch_labels)}
+depends_on = ${repr(depends_on)}
+
+
+def upgrade():
+    ${upgrades if upgrades else "pass"}
+
+
+def downgrade():
+    ${downgrades if downgrades else "pass"}
diff --git a/migrations/versions/22b5bf5541c4_.py b/migrations/versions/22b5bf5541c4_.py
new file mode 100644
index 0000000000..0e8edd6c96
--- /dev/null
+++ b/migrations/versions/22b5bf5541c4_.py
@@ -0,0 +1,35 @@
+"""empty message
+
+Revision ID: 22b5bf5541c4
+Revises: 
+Create Date: 2025-02-19 19:55:11.728525
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '22b5bf5541c4'
+down_revision = None
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('user',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('email', sa.String(length=120), nullable=False),
+    sa.Column('password', sa.String(length=80), nullable=False),
+    sa.Column('is_active', sa.Boolean(), nullable=False),
+    sa.PrimaryKeyConstraint('id'),
+    sa.UniqueConstraint('email')
+    )
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.drop_table('user')
+    # ### end Alembic commands ###
diff --git a/src/front/img/microphone.jpg b/src/front/img/microphone.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..1db21ae33c2266bdb2d6fdba74706704a21b7614
GIT binary patch
literal 112253
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

literal 0
HcmV?d00001

diff --git a/src/front/js/layout.js b/src/front/js/layout.js
index d42289f0ee..fdece58577 100755
--- a/src/front/js/layout.js
+++ b/src/front/js/layout.js
@@ -1,5 +1,5 @@
 import React from "react";
-import { BrowserRouter, Route, Routes } from "react-router-dom";
+import { BrowserRouter, Route, Routes, useLocation  } from "react-router-dom";
 import ScrollToTop from "./component/scrollToTop";
 import { BackendURL } from "./component/backendURL";
 
@@ -8,6 +8,8 @@ import { Demo } from "./pages/demo";
 import { Single } from "./pages/single";
 import injectContext from "./store/appContext";
 
+import { Login } from "./pages/login";
+
 import { Navbar } from "./component/navbar";
 import { Footer } from "./component/footer";
 
@@ -15,26 +17,41 @@ import { Footer } from "./component/footer";
 const Layout = () => {
     //the basename is used when your project is published in a subdirectory and not in the root of the domain
     // you can set the basename on the .env file located at the root of this project, E.g: BASENAME=/react-hello-webapp/
-    const basename = process.env.BASENAME || "";
-
-    if(!process.env.BACKEND_URL || process.env.BACKEND_URL == "") return <BackendURL/ >;
-
-    return (
-        <div>
+        const basename = process.env.BASENAME || "";
+    
+        if (!process.env.BACKEND_URL || process.env.BACKEND_URL === "") return <BackendURL />;
+    
+        return (
             <BrowserRouter basename={basename}>
                 <ScrollToTop>
-                    <Navbar />
-                    <Routes>
-                        <Route element={<Home />} path="/" />
-                        <Route element={<Demo />} path="/demo" />
-                        <Route element={<Single />} path="/single/:theid" />
-                        <Route element={<h1>Not found!</h1>} />
-                    </Routes>
-                    <Footer />
+                    <LayoutContent /> {/* Renderiza el contenido con la lógica de ocultar */}
                 </ScrollToTop>
             </BrowserRouter>
-        </div>
-    );
-};
+        );
+    };
+
+    const LayoutContent = () => {
+        const location = useLocation(); // Obtiene la ruta actual
+    
+        const hideNavbarFooter = location.pathname === "/login"; // Solo oculta en /login
+    
+        return (
+            <>
+                {!hideNavbarFooter && <Navbar />}
+                
+                <Routes>
+                    <Route element={<Home />} path="/" />
+                    <Route element={<Login />} path="/login" />
+                    <Route element={<Demo />} path="/demo" />
+                    <Route element={<Single />} path="/single/:theid" />
+                    <Route element={<h1>Not found!</h1>} />
+                </Routes>
+                
+                {!hideNavbarFooter && <Footer />}
+            </>
+        );
+    };
 
 export default injectContext(Layout);
+
+
diff --git a/src/front/js/pages/login.js b/src/front/js/pages/login.js
new file mode 100644
index 0000000000..42242866f1
--- /dev/null
+++ b/src/front/js/pages/login.js
@@ -0,0 +1,76 @@
+import React, { useState } from "react";
+import "../../styles/login.css";
+import microphone from "../../img/microphone.jpg";
+
+export const Login = () => {
+  // Estado para determinar si mostramos el formulario de login o registro
+  const [showLogin, setShowLogin] = useState(false);
+
+  // Función para mostrar el formulario de login
+  const showLoginForm = () => setShowLogin(true);
+
+  // Función para mostrar el formulario de registro
+  const showRegisterForm = () => setShowLogin(false);
+
+  return (
+    <div
+      style={{
+        backgroundImage: `url(${microphone})`,
+        backgroundSize: "cover",
+        backgroundPosition: "center",
+        height: "100vh",
+        display: "flex",
+        justifyContent: "center",
+        alignItems: "center"
+      }}
+    >
+      <div
+        className="login-container p-4 shadow-lg rounded-3 w-100"
+        style={{ maxWidth: "400px", background: "rgba(255, 255, 255, 0.5)" }}
+      >
+        {!showLogin ? (
+          // Pantalla inicial con los botones
+          <div>
+            <h2 className="text-center mb-4">Bienvenido</h2>
+            <button
+              className="btn btn-primary w-100 mb-3"
+              onClick={showLoginForm}
+            >
+              Iniciar sesión
+            </button>
+            <button
+              className="btn btn-secondary w-100"
+              onClick={showRegisterForm}
+            >
+              Registrarse
+            </button>
+          </div>
+        ) : (
+          // Formulario de login
+          <form>
+            <h2 className="text-center mb-4">Iniciar sesión</h2>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Nombre de usuario"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="password"
+                className="form-control form-control-lg"
+                placeholder="Contraseña"
+                required
+              />
+            </div>
+            <button type="submit" className="btn btn-danger w-100 py-2">
+              Ingresar
+            </button>
+          </form>
+        )}
+      </div>
+    </div>
+  );
+};
diff --git a/src/front/styles/home.css b/src/front/styles/home.css
index 194b236ac4..7e32217b3e 100755
--- a/src/front/styles/home.css
+++ b/src/front/styles/home.css
@@ -4,4 +4,12 @@
     All pages share the styles on index.css but you should create 
     one more css for each page that will contain the selected used 
     on that page only (the ones not reused in other pages).
-*/
\ No newline at end of file
+*/
+
+body {
+    background: url(../img/microphone.jpg);
+    background-size: cover;
+    background-repeat: no-repeat;
+    margin: 0;
+    height: 100vh;
+  }
\ No newline at end of file
diff --git a/src/front/styles/login.css b/src/front/styles/login.css
new file mode 100644
index 0000000000..342737402e
--- /dev/null
+++ b/src/front/styles/login.css
@@ -0,0 +1,7 @@
+.red {
+    background: url(../img/microphone.jpg);
+    background-size: cover;
+    background-repeat: no-repeat;
+    margin: 0;
+    height: 100vh;
+  }
\ No newline at end of file

From 16577024197ed2d25cdbd85fd54f5857f757c1e8 Mon Sep 17 00:00:00 2001
From: Jaime BP <jaimebernet@gmail.com>
Date: Fri, 21 Feb 2025 18:19:39 +0000
Subject: [PATCH 02/25] First Commit

---
 Pipfile.lock                         | 654 +++++++++++++++------------
 migrations/README                    |   1 +
 migrations/alembic.ini               |  50 ++
 migrations/env.py                    | 113 +++++
 migrations/script.py.mako            |  24 +
 migrations/versions/34a3df02bba3_.py |  35 ++
 src/front/js/component/navbar.js     |  41 +-
 src/front/js/layout.js               |   7 +
 src/front/js/pages/SavedArtists.js   |  35 ++
 src/front/js/pages/SavedSongs.js     |  34 ++
 src/front/js/pages/UserProfile.js    |  15 +
 src/front/styles/index.css           |  14 +-
 src/front/styles/navbar.css          |  62 +++
 src/front/styles/userProfile.css     |  68 +++
 14 files changed, 838 insertions(+), 315 deletions(-)
 create mode 100644 migrations/README
 create mode 100644 migrations/alembic.ini
 create mode 100644 migrations/env.py
 create mode 100644 migrations/script.py.mako
 create mode 100644 migrations/versions/34a3df02bba3_.py
 create mode 100644 src/front/js/pages/SavedArtists.js
 create mode 100644 src/front/js/pages/SavedSongs.js
 create mode 100644 src/front/js/pages/UserProfile.js
 create mode 100644 src/front/styles/navbar.css
 create mode 100644 src/front/styles/userProfile.css

diff --git a/Pipfile.lock b/Pipfile.lock
index a391864e9d..508225b0a1 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "74f92d76f687bb774828613a3a513123fe2ffdb429b95b351d29721dddfd3fb8"
+            "sha256": "4f0e9a772f04b621ff0313b7ecfa468af1526aa27df8bfcacac6955d499d352d"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -18,73 +18,91 @@
     "default": {
         "alembic": {
             "hashes": [
-                "sha256:6880dec4f28dd7bd999d2ed13fbe7c9d4337700a44d11a524c0ce0c59aaf0dbd",
-                "sha256:e8a6ff9f3b1887e1fed68bfb8fb9a000d8f61c21bdcc85b67bb9f87fcbc4fce3"
+                "sha256:1acdd7a3a478e208b0503cd73614d5e4c6efafa4e73518bb60e4f2846a37b1c5",
+                "sha256:496e888245a53adf1498fcab31713a469c65836f8de76e01399aa1c3e90dd213"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==1.9.2"
+            "markers": "python_version >= '3.8'",
+            "version": "==1.14.1"
+        },
+        "blinker": {
+            "hashes": [
+                "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf",
+                "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"
+            ],
+            "markers": "python_version >= '3.9'",
+            "version": "==1.9.0"
         },
         "certifi": {
             "hashes": [
-                "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
-                "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
+                "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651",
+                "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"
             ],
             "markers": "python_version >= '3.6'",
-            "version": "==2022.12.7"
+            "version": "==2025.1.31"
         },
         "click": {
             "hashes": [
-                "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
-                "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
+                "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2",
+                "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==8.1.3"
+            "version": "==8.1.8"
         },
         "cloudinary": {
             "hashes": [
-                "sha256:f52a1f5eb2c6820f13aa01c109caa5937ad3fd6caf5967817d0ef6c113403afc"
+                "sha256:ba223705409b2aaddd5196c2184d65f50a83dffcba3b94f3727658ff6a0172a3",
+                "sha256:e4191b470c5bae55542b64e0a78659af42971880294456dca480bc974fa9280a"
             ],
             "index": "pypi",
-            "version": "==1.31.0"
+            "version": "==1.42.2"
         },
         "flask": {
             "hashes": [
-                "sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b",
-                "sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526"
+                "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac",
+                "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136"
             ],
             "index": "pypi",
-            "version": "==2.2.2"
+            "version": "==3.1.0"
         },
         "flask-admin": {
             "hashes": [
-                "sha256:424ffc79b7b0dfff051555686ea12e86e48dffacac14beaa319fb4502ac40988"
+                "sha256:24cae2af832b6a611a01d7dc35f42d266c1d6c75a426b869d8cb241b78233369",
+                "sha256:fd8190f1ec3355913a22739c46ed3623f1d82b8112cde324c60a6fc9b21c9406"
             ],
             "index": "pypi",
-            "version": "==1.6.0"
+            "version": "==1.6.1"
         },
         "flask-cors": {
             "hashes": [
-                "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438",
-                "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"
+                "sha256:5aadb4b950c4e93745034594d9f3ea6591f734bb3662e16e255ffbf5e89c88ef",
+                "sha256:b9e307d082a9261c100d8fb0ba909eec6a228ed1b60a8315fd85f783d61910bc"
+            ],
+            "index": "pypi",
+            "version": "==5.0.0"
+        },
+        "flask-jwt-extended": {
+            "hashes": [
+                "sha256:63a28fc9731bcc6c4b8815b6f954b5904caa534fc2ae9b93b1d3ef12930dca95",
+                "sha256:9215d05a9413d3855764bcd67035e75819d23af2fafb6b55197eb5a3313fdfb2"
             ],
             "index": "pypi",
-            "version": "==3.0.10"
+            "version": "==4.6.0"
         },
         "flask-migrate": {
             "hashes": [
-                "sha256:8662a9dd391ce36deeaf3265987319c20fdb4c8a45306a32ba4f8224459abed4",
-                "sha256:a0062c8d3f32de02847086b46cfc389412f78c71c89a619ebd7097e89d72ea4b"
+                "sha256:1a336b06eb2c3ace005f5f2ded8641d534c18798d64061f6ff11f79e1434126d",
+                "sha256:24d8051af161782e0743af1b04a152d007bad9772b2bca67b7ec1e8ceeb3910d"
             ],
             "index": "pypi",
-            "version": "==4.0.3"
+            "version": "==4.1.0"
         },
         "flask-sqlalchemy": {
             "hashes": [
-                "sha256:2764335f3c9d7ebdc9ed6044afaf98aae9fa50d7a074cef55dde307ec95903ec",
-                "sha256:add5750b2f9cd10512995261ee2aa23fab85bd5626061aa3c564b33bb4aa780a"
+                "sha256:c5765e58ca145401b52106c0f46178569243c5da25556be2c231ecc60867c5b1",
+                "sha256:cabb6600ddd819a9f859f36515bb1bd8e7dbf30206cc679d2b081dff9e383283"
             ],
             "index": "pypi",
-            "version": "==3.0.3"
+            "version": "==3.0.5"
         },
         "flask-swagger": {
             "hashes": [
@@ -96,304 +114,346 @@
         },
         "greenlet": {
             "hashes": [
-                "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a",
-                "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a",
-                "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43",
-                "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33",
-                "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8",
-                "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088",
-                "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca",
-                "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343",
-                "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645",
-                "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db",
-                "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df",
-                "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3",
-                "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86",
-                "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2",
-                "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a",
-                "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf",
-                "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7",
-                "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394",
-                "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40",
-                "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3",
-                "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6",
-                "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74",
-                "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0",
-                "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3",
-                "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91",
-                "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5",
-                "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9",
-                "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8",
-                "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b",
-                "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6",
-                "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb",
-                "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73",
-                "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b",
-                "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df",
-                "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9",
-                "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f",
-                "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0",
-                "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857",
-                "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a",
-                "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249",
-                "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30",
-                "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292",
-                "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b",
-                "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d",
-                "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b",
-                "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c",
-                "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca",
-                "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7",
-                "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75",
-                "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae",
-                "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b",
-                "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470",
-                "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564",
-                "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9",
-                "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099",
-                "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0",
-                "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5",
-                "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19",
-                "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1",
-                "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"
+                "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e",
+                "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7",
+                "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01",
+                "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1",
+                "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159",
+                "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563",
+                "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83",
+                "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9",
+                "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395",
+                "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa",
+                "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942",
+                "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1",
+                "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441",
+                "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22",
+                "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9",
+                "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0",
+                "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba",
+                "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3",
+                "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1",
+                "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6",
+                "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291",
+                "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39",
+                "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d",
+                "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467",
+                "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475",
+                "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef",
+                "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c",
+                "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511",
+                "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c",
+                "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822",
+                "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a",
+                "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8",
+                "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d",
+                "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01",
+                "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145",
+                "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80",
+                "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13",
+                "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e",
+                "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b",
+                "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1",
+                "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef",
+                "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc",
+                "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff",
+                "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120",
+                "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437",
+                "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd",
+                "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981",
+                "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36",
+                "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a",
+                "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798",
+                "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7",
+                "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761",
+                "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0",
+                "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e",
+                "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af",
+                "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa",
+                "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c",
+                "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42",
+                "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e",
+                "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81",
+                "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e",
+                "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617",
+                "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc",
+                "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de",
+                "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111",
+                "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383",
+                "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70",
+                "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6",
+                "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4",
+                "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011",
+                "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803",
+                "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79",
+                "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f"
             ],
             "markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))",
-            "version": "==2.0.2"
+            "version": "==3.1.1"
         },
         "gunicorn": {
             "hashes": [
-                "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
-                "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
+                "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d",
+                "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"
             ],
             "index": "pypi",
-            "version": "==20.1.0"
+            "version": "==23.0.0"
         },
         "itsdangerous": {
             "hashes": [
-                "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
-                "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
+                "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
+                "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==2.1.2"
+            "markers": "python_version >= '3.8'",
+            "version": "==2.2.0"
         },
         "jinja2": {
             "hashes": [
-                "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
-                "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
+                "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb",
+                "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==3.1.2"
+            "version": "==3.1.5"
         },
         "mako": {
             "hashes": [
-                "sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818",
-                "sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34"
+                "sha256:95920acccb578427a9aa38e37a186b1e43156c87260d7ba18ca63aa4c7cbd3a1",
+                "sha256:b5d65ff3462870feec922dbccf38f6efb44e5714d7b593a656be86663d8600ac"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==1.2.4"
+            "markers": "python_version >= '3.8'",
+            "version": "==1.3.9"
         },
         "markupsafe": {
             "hashes": [
-                "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed",
-                "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc",
-                "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2",
-                "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460",
-                "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7",
-                "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0",
-                "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1",
-                "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa",
-                "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03",
-                "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323",
-                "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65",
-                "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013",
-                "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036",
-                "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f",
-                "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4",
-                "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419",
-                "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2",
-                "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619",
-                "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a",
-                "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a",
-                "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd",
-                "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7",
-                "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666",
-                "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65",
-                "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859",
-                "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625",
-                "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff",
-                "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156",
-                "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd",
-                "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba",
-                "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f",
-                "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1",
-                "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094",
-                "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a",
-                "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513",
-                "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed",
-                "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d",
-                "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3",
-                "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147",
-                "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c",
-                "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603",
-                "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601",
-                "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a",
-                "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1",
-                "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d",
-                "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3",
-                "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54",
-                "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2",
-                "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6",
-                "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"
+                "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4",
+                "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30",
+                "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0",
+                "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9",
+                "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396",
+                "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13",
+                "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028",
+                "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca",
+                "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557",
+                "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832",
+                "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0",
+                "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b",
+                "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579",
+                "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a",
+                "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c",
+                "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff",
+                "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c",
+                "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22",
+                "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094",
+                "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb",
+                "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e",
+                "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5",
+                "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a",
+                "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d",
+                "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a",
+                "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b",
+                "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8",
+                "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225",
+                "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c",
+                "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144",
+                "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f",
+                "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87",
+                "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d",
+                "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93",
+                "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf",
+                "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158",
+                "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84",
+                "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb",
+                "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48",
+                "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171",
+                "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c",
+                "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6",
+                "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd",
+                "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d",
+                "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1",
+                "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d",
+                "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca",
+                "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a",
+                "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29",
+                "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe",
+                "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798",
+                "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c",
+                "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8",
+                "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f",
+                "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f",
+                "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a",
+                "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178",
+                "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0",
+                "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79",
+                "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430",
+                "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==2.1.2"
+            "markers": "python_version >= '3.9'",
+            "version": "==3.0.2"
+        },
+        "packaging": {
+            "hashes": [
+                "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
+                "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"
+            ],
+            "markers": "python_version >= '3.8'",
+            "version": "==24.2"
         },
         "psycopg2-binary": {
             "hashes": [
-                "sha256:00475004e5ed3e3bf5e056d66e5dcdf41a0dc62efcd57997acd9135c40a08a50",
-                "sha256:01ad49d68dd8c5362e4bfb4158f2896dc6e0c02e87b8a3770fc003459f1a4425",
-                "sha256:024030b13bdcbd53d8a93891a2cf07719715724fc9fee40243f3bd78b4264b8f",
-                "sha256:02551647542f2bf89073d129c73c05a25c372fc0a49aa50e0de65c3c143d8bd0",
-                "sha256:043a9fd45a03858ff72364b4b75090679bd875ee44df9c0613dc862ca6b98460",
-                "sha256:05b3d479425e047c848b9782cd7aac9c6727ce23181eb9647baf64ffdfc3da41",
-                "sha256:0775d6252ccb22b15da3b5d7adbbf8cfe284916b14b6dc0ff503a23edb01ee85",
-                "sha256:1764546ffeaed4f9428707be61d68972eb5ede81239b46a45843e0071104d0dd",
-                "sha256:1e491e6489a6cb1d079df8eaa15957c277fdedb102b6a68cfbf40c4994412fd0",
-                "sha256:212757ffcecb3e1a5338d4e6761bf9c04f750e7d027117e74aa3cd8a75bb6fbd",
-                "sha256:215d6bf7e66732a514f47614f828d8c0aaac9a648c46a831955cb103473c7147",
-                "sha256:25382c7d174c679ce6927c16b6fbb68b10e56ee44b1acb40671e02d29f2fce7c",
-                "sha256:2abccab84d057723d2ca8f99ff7b619285d40da6814d50366f61f0fc385c3903",
-                "sha256:2d964eb24c8b021623df1c93c626671420c6efadbdb8655cb2bd5e0c6fa422ba",
-                "sha256:2ec46ed947801652c9643e0b1dc334cfb2781232e375ba97312c2fc256597632",
-                "sha256:2ef892cabdccefe577088a79580301f09f2a713eb239f4f9f62b2b29cafb0577",
-                "sha256:33e632d0885b95a8b97165899006c40e9ecdc634a529dca7b991eb7de4ece41c",
-                "sha256:3520d7af1ebc838cc6084a3281145d5cd5bdd43fdef139e6db5af01b92596cb7",
-                "sha256:3d790f84201c3698d1bfb404c917f36e40531577a6dda02e45ba29b64d539867",
-                "sha256:3fc33295cfccad697a97a76dec3f1e94ad848b7b163c3228c1636977966b51e2",
-                "sha256:422e3d43b47ac20141bc84b3d342eead8d8099a62881a501e97d15f6addabfe9",
-                "sha256:426c2ae999135d64e6a18849a7d1ad0e1bd007277e4a8f4752eaa40a96b550ff",
-                "sha256:46512486be6fbceef51d7660dec017394ba3e170299d1dc30928cbedebbf103a",
-                "sha256:46850a640df62ae940e34a163f72e26aca1f88e2da79148e1862faaac985c302",
-                "sha256:484405b883630f3e74ed32041a87456c5e0e63a8e3429aa93e8714c366d62bd1",
-                "sha256:4e7904d1920c0c89105c0517dc7e3f5c20fb4e56ba9cdef13048db76947f1d79",
-                "sha256:56b2957a145f816726b109ee3d4e6822c23f919a7d91af5a94593723ed667835",
-                "sha256:5c6527c8efa5226a9e787507652dd5ba97b62d29b53c371a85cd13f957fe4d42",
-                "sha256:5cbc554ba47ecca8cd3396ddaca85e1ecfe3e48dd57dc5e415e59551affe568e",
-                "sha256:5d28ecdf191db558d0c07d0f16524ee9d67896edf2b7990eea800abeb23ebd61",
-                "sha256:5fc447058d083b8c6ac076fc26b446d44f0145308465d745fba93a28c14c9e32",
-                "sha256:63e318dbe52709ed10d516a356f22a635e07a2e34c68145484ed96a19b0c4c68",
-                "sha256:68d81a2fe184030aa0c5c11e518292e15d342a667184d91e30644c9d533e53e1",
-                "sha256:6e63814ec71db9bdb42905c925639f319c80e7909fb76c3b84edc79dadef8d60",
-                "sha256:6f8a9bcab7b6db2e3dbf65b214dfc795b4c6b3bb3af922901b6a67f7cb47d5f8",
-                "sha256:70831e03bd53702c941da1a1ad36c17d825a24fbb26857b40913d58df82ec18b",
-                "sha256:74eddec4537ab1f701a1647214734bc52cee2794df748f6ae5908e00771f180a",
-                "sha256:7b3751857da3e224f5629400736a7b11e940b5da5f95fa631d86219a1beaafec",
-                "sha256:7cf1d44e710ca3a9ce952bda2855830fe9f9017ed6259e01fcd71ea6287565f5",
-                "sha256:7d07f552d1e412f4b4e64ce386d4c777a41da3b33f7098b6219012ba534fb2c2",
-                "sha256:7d88db096fa19d94f433420eaaf9f3c45382da2dd014b93e4bf3215639047c16",
-                "sha256:7ee3095d02d6f38bd7d9a5358fcc9ea78fcdb7176921528dd709cc63f40184f5",
-                "sha256:902844f9c4fb19b17dfa84d9e2ca053d4a4ba265723d62ea5c9c26b38e0aa1e6",
-                "sha256:937880290775033a743f4836aa253087b85e62784b63fd099ee725d567a48aa1",
-                "sha256:95076399ec3b27a8f7fa1cc9a83417b1c920d55cf7a97f718a94efbb96c7f503",
-                "sha256:9c38d3869238e9d3409239bc05bc27d6b7c99c2a460ea337d2814b35fb4fea1b",
-                "sha256:9e32cedc389bcb76d9f24ea8a012b3cb8385ee362ea437e1d012ffaed106c17d",
-                "sha256:9ffdc51001136b699f9563b1c74cc1f8c07f66ef7219beb6417a4c8aaa896c28",
-                "sha256:a0adef094c49f242122bb145c3c8af442070dc0e4312db17e49058c1702606d4",
-                "sha256:a36a0e791805aa136e9cbd0ffa040d09adec8610453ee8a753f23481a0057af5",
-                "sha256:a7e518a0911c50f60313cb9e74a169a65b5d293770db4770ebf004245f24b5c5",
-                "sha256:af0516e1711995cb08dc19bbd05bec7dbdebf4185f68870595156718d237df3e",
-                "sha256:b8104f709590fff72af801e916817560dbe1698028cd0afe5a52d75ceb1fce5f",
-                "sha256:b911dfb727e247340d36ae20c4b9259e4a64013ab9888ccb3cbba69b77fd9636",
-                "sha256:b9a794cef1d9c1772b94a72eec6da144c18e18041d294a9ab47669bc77a80c1d",
-                "sha256:b9c33d4aef08dfecbd1736ceab8b7b3c4358bf10a0121483e5cd60d3d308cc64",
-                "sha256:b9d38a4656e4e715d637abdf7296e98d6267df0cc0a8e9a016f8ba07e4aa3eeb",
-                "sha256:bcda1c84a1c533c528356da5490d464a139b6e84eb77cc0b432e38c5c6dd7882",
-                "sha256:bef7e3f9dc6f0c13afdd671008534be5744e0e682fb851584c8c3a025ec09720",
-                "sha256:c15ba5982c177bc4b23a7940c7e4394197e2d6a424a2d282e7c236b66da6d896",
-                "sha256:c5254cbd4f4855e11cebf678c1a848a3042d455a22a4ce61349c36aafd4c2267",
-                "sha256:c5682a45df7d9642eff590abc73157c887a68f016df0a8ad722dcc0f888f56d7",
-                "sha256:c5e65c6ac0ae4bf5bef1667029f81010b6017795dcb817ba5c7b8a8d61fab76f",
-                "sha256:d4c7b3a31502184e856df1f7bbb2c3735a05a8ce0ade34c5277e1577738a5c91",
-                "sha256:d892bfa1d023c3781a3cab8dd5af76b626c483484d782e8bd047c180db590e4c",
-                "sha256:dbc332beaf8492b5731229a881807cd7b91b50dbbbaf7fe2faf46942eda64a24",
-                "sha256:dc85b3777068ed30aff8242be2813038a929f2084f69e43ef869daddae50f6ee",
-                "sha256:e59137cdb970249ae60be2a49774c6dfb015bd0403f05af1fe61862e9626642d",
-                "sha256:e67b3c26e9b6d37b370c83aa790bbc121775c57bfb096c2e77eacca25fd0233b",
-                "sha256:e72c91bda9880f097c8aa3601a2c0de6c708763ba8128006151f496ca9065935",
-                "sha256:f95b8aca2703d6a30249f83f4fe6a9abf2e627aa892a5caaab2267d56be7ab69"
+                "sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff",
+                "sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5",
+                "sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f",
+                "sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5",
+                "sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0",
+                "sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c",
+                "sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c",
+                "sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341",
+                "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f",
+                "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7",
+                "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d",
+                "sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007",
+                "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142",
+                "sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92",
+                "sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb",
+                "sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5",
+                "sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5",
+                "sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8",
+                "sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1",
+                "sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68",
+                "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73",
+                "sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1",
+                "sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53",
+                "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d",
+                "sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906",
+                "sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0",
+                "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2",
+                "sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a",
+                "sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b",
+                "sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44",
+                "sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648",
+                "sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7",
+                "sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f",
+                "sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa",
+                "sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697",
+                "sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d",
+                "sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b",
+                "sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526",
+                "sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4",
+                "sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287",
+                "sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e",
+                "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673",
+                "sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0",
+                "sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30",
+                "sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3",
+                "sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e",
+                "sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92",
+                "sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a",
+                "sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c",
+                "sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8",
+                "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909",
+                "sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47",
+                "sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864",
+                "sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc",
+                "sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00",
+                "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb",
+                "sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539",
+                "sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b",
+                "sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481",
+                "sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5",
+                "sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4",
+                "sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64",
+                "sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392",
+                "sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4",
+                "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1",
+                "sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1",
+                "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567",
+                "sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863"
             ],
             "index": "pypi",
-            "version": "==2.9.5"
+            "version": "==2.9.10"
         },
-        "python-dotenv": {
+        "pyjwt": {
             "hashes": [
-                "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49",
-                "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"
+                "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953",
+                "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"
             ],
-            "index": "pypi",
-            "version": "==0.21.1"
+            "markers": "python_version >= '3.9'",
+            "version": "==2.10.1"
         },
-        "pyyaml": {
+        "python-dotenv": {
             "hashes": [
-                "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf",
-                "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293",
-                "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b",
-                "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57",
-                "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b",
-                "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4",
-                "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07",
-                "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba",
-                "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9",
-                "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287",
-                "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513",
-                "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0",
-                "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782",
-                "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0",
-                "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92",
-                "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f",
-                "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2",
-                "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc",
-                "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1",
-                "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c",
-                "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86",
-                "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4",
-                "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c",
-                "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34",
-                "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b",
-                "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d",
-                "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c",
-                "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb",
-                "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7",
-                "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737",
-                "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3",
-                "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d",
-                "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358",
-                "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53",
-                "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78",
-                "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803",
-                "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a",
-                "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f",
-                "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174",
-                "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"
+                "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca",
+                "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==6.0"
+            "index": "pypi",
+            "version": "==1.0.1"
         },
-        "setuptools": {
+        "pyyaml": {
             "hashes": [
-                "sha256:a7687c12b444eaac951ea87a9627c4f904ac757e7abdc5aac32833234af90378",
-                "sha256:e261cdf010c11a41cb5cb5f1bf3338a7433832029f559a6a7614bd42a967c300"
+                "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff",
+                "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48",
+                "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086",
+                "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e",
+                "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133",
+                "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5",
+                "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484",
+                "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee",
+                "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5",
+                "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68",
+                "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a",
+                "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf",
+                "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99",
+                "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8",
+                "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85",
+                "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19",
+                "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc",
+                "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a",
+                "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1",
+                "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317",
+                "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c",
+                "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631",
+                "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d",
+                "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652",
+                "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5",
+                "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e",
+                "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b",
+                "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8",
+                "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476",
+                "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706",
+                "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563",
+                "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237",
+                "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b",
+                "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083",
+                "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180",
+                "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425",
+                "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e",
+                "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f",
+                "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725",
+                "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183",
+                "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab",
+                "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774",
+                "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725",
+                "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e",
+                "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5",
+                "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d",
+                "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290",
+                "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44",
+                "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed",
+                "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4",
+                "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba",
+                "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12",
+                "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==67.1.0"
+            "markers": "python_version >= '3.8'",
+            "version": "==6.0.2"
         },
         "six": {
             "hashes": [
-                "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
-                "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+                "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
+                "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
             ],
             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==1.16.0"
+            "version": "==1.17.0"
         },
         "sqlalchemy": {
             "hashes": [
@@ -444,35 +504,35 @@
         },
         "typing-extensions": {
             "hashes": [
-                "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa",
-                "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"
+                "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d",
+                "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"
             ],
             "index": "pypi",
-            "version": "==4.4.0"
+            "version": "==4.12.2"
         },
         "urllib3": {
             "hashes": [
-                "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72",
-                "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"
+                "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df",
+                "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
-            "version": "==1.26.14"
+            "markers": "python_version >= '3.9'",
+            "version": "==2.3.0"
         },
         "werkzeug": {
             "hashes": [
-                "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f",
-                "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5"
+                "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e",
+                "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==2.2.2"
+            "markers": "python_version >= '3.9'",
+            "version": "==3.1.3"
         },
         "wtforms": {
             "hashes": [
-                "sha256:6b351bbb12dd58af57ffef05bc78425d08d1914e0fd68ee14143b7ade023c5bc",
-                "sha256:837f2f0e0ca79481b92884962b914eba4e72b7a2daaf1f939c890ed0124b834b"
+                "sha256:bf831c042829c8cdbad74c27575098d541d039b1faa74c771545ecac916f2c07",
+                "sha256:f8d76180d7239c94c6322f7990ae1216dae3659b7aa1cee94b6318bdffb474b9"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==3.0.1"
+            "index": "pypi",
+            "version": "==3.1.2"
         }
     },
     "develop": {}
diff --git a/migrations/README b/migrations/README
new file mode 100644
index 0000000000..0e04844159
--- /dev/null
+++ b/migrations/README
@@ -0,0 +1 @@
+Single-database configuration for Flask.
diff --git a/migrations/alembic.ini b/migrations/alembic.ini
new file mode 100644
index 0000000000..ec9d45c26a
--- /dev/null
+++ b/migrations/alembic.ini
@@ -0,0 +1,50 @@
+# A generic, single database configuration.
+
+[alembic]
+# template used to generate migration files
+# file_template = %%(rev)s_%%(slug)s
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic,flask_migrate
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[logger_flask_migrate]
+level = INFO
+handlers =
+qualname = flask_migrate
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S
diff --git a/migrations/env.py b/migrations/env.py
new file mode 100644
index 0000000000..4c9709271b
--- /dev/null
+++ b/migrations/env.py
@@ -0,0 +1,113 @@
+import logging
+from logging.config import fileConfig
+
+from flask import current_app
+
+from alembic import context
+
+# this is the Alembic Config object, which provides
+# access to the values within the .ini file in use.
+config = context.config
+
+# Interpret the config file for Python logging.
+# This line sets up loggers basically.
+fileConfig(config.config_file_name)
+logger = logging.getLogger('alembic.env')
+
+
+def get_engine():
+    try:
+        # this works with Flask-SQLAlchemy<3 and Alchemical
+        return current_app.extensions['migrate'].db.get_engine()
+    except (TypeError, AttributeError):
+        # this works with Flask-SQLAlchemy>=3
+        return current_app.extensions['migrate'].db.engine
+
+
+def get_engine_url():
+    try:
+        return get_engine().url.render_as_string(hide_password=False).replace(
+            '%', '%%')
+    except AttributeError:
+        return str(get_engine().url).replace('%', '%%')
+
+
+# add your model's MetaData object here
+# for 'autogenerate' support
+# from myapp import mymodel
+# target_metadata = mymodel.Base.metadata
+config.set_main_option('sqlalchemy.url', get_engine_url())
+target_db = current_app.extensions['migrate'].db
+
+# other values from the config, defined by the needs of env.py,
+# can be acquired:
+# my_important_option = config.get_main_option("my_important_option")
+# ... etc.
+
+
+def get_metadata():
+    if hasattr(target_db, 'metadatas'):
+        return target_db.metadatas[None]
+    return target_db.metadata
+
+
+def run_migrations_offline():
+    """Run migrations in 'offline' mode.
+
+    This configures the context with just a URL
+    and not an Engine, though an Engine is acceptable
+    here as well.  By skipping the Engine creation
+    we don't even need a DBAPI to be available.
+
+    Calls to context.execute() here emit the given string to the
+    script output.
+
+    """
+    url = config.get_main_option("sqlalchemy.url")
+    context.configure(
+        url=url, target_metadata=get_metadata(), literal_binds=True
+    )
+
+    with context.begin_transaction():
+        context.run_migrations()
+
+
+def run_migrations_online():
+    """Run migrations in 'online' mode.
+
+    In this scenario we need to create an Engine
+    and associate a connection with the context.
+
+    """
+
+    # this callback is used to prevent an auto-migration from being generated
+    # when there are no changes to the schema
+    # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
+    def process_revision_directives(context, revision, directives):
+        if getattr(config.cmd_opts, 'autogenerate', False):
+            script = directives[0]
+            if script.upgrade_ops.is_empty():
+                directives[:] = []
+                logger.info('No changes in schema detected.')
+
+    conf_args = current_app.extensions['migrate'].configure_args
+    if conf_args.get("process_revision_directives") is None:
+        conf_args["process_revision_directives"] = process_revision_directives
+
+    connectable = get_engine()
+
+    with connectable.connect() as connection:
+        context.configure(
+            connection=connection,
+            target_metadata=get_metadata(),
+            **conf_args
+        )
+
+        with context.begin_transaction():
+            context.run_migrations()
+
+
+if context.is_offline_mode():
+    run_migrations_offline()
+else:
+    run_migrations_online()
diff --git a/migrations/script.py.mako b/migrations/script.py.mako
new file mode 100644
index 0000000000..2c0156303a
--- /dev/null
+++ b/migrations/script.py.mako
@@ -0,0 +1,24 @@
+"""${message}
+
+Revision ID: ${up_revision}
+Revises: ${down_revision | comma,n}
+Create Date: ${create_date}
+
+"""
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
+
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+branch_labels = ${repr(branch_labels)}
+depends_on = ${repr(depends_on)}
+
+
+def upgrade():
+    ${upgrades if upgrades else "pass"}
+
+
+def downgrade():
+    ${downgrades if downgrades else "pass"}
diff --git a/migrations/versions/34a3df02bba3_.py b/migrations/versions/34a3df02bba3_.py
new file mode 100644
index 0000000000..feceaccec3
--- /dev/null
+++ b/migrations/versions/34a3df02bba3_.py
@@ -0,0 +1,35 @@
+"""empty message
+
+Revision ID: 34a3df02bba3
+Revises: 
+Create Date: 2025-02-21 09:53:15.839016
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '34a3df02bba3'
+down_revision = None
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('user',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('email', sa.String(length=120), nullable=False),
+    sa.Column('password', sa.String(length=80), nullable=False),
+    sa.Column('is_active', sa.Boolean(), nullable=False),
+    sa.PrimaryKeyConstraint('id'),
+    sa.UniqueConstraint('email')
+    )
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.drop_table('user')
+    # ### end Alembic commands ###
diff --git a/src/front/js/component/navbar.js b/src/front/js/component/navbar.js
index af4b01e334..3be878d86e 100755
--- a/src/front/js/component/navbar.js
+++ b/src/front/js/component/navbar.js
@@ -1,19 +1,30 @@
-import React from "react";
+import React, { useState } from "react";
 import { Link } from "react-router-dom";
+import "../../styles/navbar.css";
 
 export const Navbar = () => {
-	return (
-		<nav className="navbar navbar-light bg-light">
-			<div className="container">
-				<Link to="/">
-					<span className="navbar-brand mb-0 h1">React Boilerplate</span>
-				</Link>
-				<div className="ml-auto">
-					<Link to="/demo">
-						<button className="btn btn-primary">Check the Context in action</button>
-					</Link>
-				</div>
-			</div>
-		</nav>
-	);
+    const [menuOpen, setMenuOpen] = useState(false);
+
+    const toggleMenu = () => {
+        setMenuOpen(!menuOpen);
+    };
+
+    return (
+        <nav className="navbar">
+            <div className="container">
+                <Link to="/" className="navbar-brand">SoundCript</Link>
+
+                {/* Botón de menú hamburguesa */}
+                <div className="menu-icon" onClick={toggleMenu}>
+                    ☰
+                </div>
+
+                {/* Menú desplegable */}
+                <div className={`dropdown-menu ${menuOpen ? "show" : ""}`}>
+                    <Link to="/userProfile" className="dropdown-item" onClick={() => setMenuOpen(false)}>Perfil</Link>
+                    <Link to="/logout" className="dropdown-item" onClick={() => setMenuOpen(false)}>Logout</Link>
+                </div>
+            </div>
+        </nav>
+    );
 };
diff --git a/src/front/js/layout.js b/src/front/js/layout.js
index d42289f0ee..1387025646 100755
--- a/src/front/js/layout.js
+++ b/src/front/js/layout.js
@@ -8,6 +8,10 @@ import { Demo } from "./pages/demo";
 import { Single } from "./pages/single";
 import injectContext from "./store/appContext";
 
+import { UserProfile } from "./pages/UserProfile"; // ✅ Nueva vista
+import { SavedSongs } from "./pages/SavedSongs"; // ✅ Nueva vista
+import { SavedArtists } from "./pages/SavedArtists"; // ✅ Nueva vista
+
 import { Navbar } from "./component/navbar";
 import { Footer } from "./component/footer";
 
@@ -28,6 +32,9 @@ const Layout = () => {
                         <Route element={<Home />} path="/" />
                         <Route element={<Demo />} path="/demo" />
                         <Route element={<Single />} path="/single/:theid" />
+                        <Route element={<UserProfile />} path="/userProfile" />  {/* ✅ nueva */}
+                        <Route element={<SavedSongs />} path="/savedSongs" />  {/* ✅ nueva */}
+                        <Route element={<SavedArtists />} path="/savedArtists" />  {/* ✅ nueva */}
                         <Route element={<h1>Not found!</h1>} />
                     </Routes>
                     <Footer />
diff --git a/src/front/js/pages/SavedArtists.js b/src/front/js/pages/SavedArtists.js
new file mode 100644
index 0000000000..6d76f72787
--- /dev/null
+++ b/src/front/js/pages/SavedArtists.js
@@ -0,0 +1,35 @@
+import React, { useState } from "react";
+import { Link } from "react-router-dom";
+import "../../styles/userProfile.css";
+
+export const SavedArtists = () => {
+    const [artists, setArtists] = useState([
+        { id: 1, name: "Artist A", image: "https://via.placeholder.com/50" },
+        { id: 2, name: "Artist B", image: "https://via.placeholder.com/50" }
+    ]);
+
+    const removeArtist = (id) => {
+        setArtists(artists.filter(artist => artist.id !== id));
+    };
+
+    return (
+        <div className="profile-container">
+            <h2>🎤 Artistas Seguidos</h2>
+            <div className="options">
+                <Link to="/savedSongs" className="option-button">🎵 Canciones Guardadas</Link>
+                <Link to="/savedArtists" className="option-button active">🎤 Artistas Seguidos</Link>
+            </div>
+            {artists.length === 0 ? <p>No sigues a ningún artista.</p> : (
+                <ul>
+                    {artists.map(artist => (
+                        <li key={artist.id}>
+                            <img src={artist.image} alt={artist.name} />
+                            {artist.name}
+                            <button onClick={() => removeArtist(artist.id)}>❌</button>
+                        </li>
+                    ))}
+                </ul>
+            )}
+        </div>
+    );
+};
diff --git a/src/front/js/pages/SavedSongs.js b/src/front/js/pages/SavedSongs.js
new file mode 100644
index 0000000000..d99dd283b0
--- /dev/null
+++ b/src/front/js/pages/SavedSongs.js
@@ -0,0 +1,34 @@
+import React, { useState } from "react";
+import { Link } from "react-router-dom";
+import "../../styles/userProfile.css";
+
+export const SavedSongs = () => {
+    const [songs, setSongs] = useState([
+        { id: 1, title: "Song 1", artist: "Artist A" },
+        { id: 2, title: "Song 2", artist: "Artist B" }
+    ]);
+
+    const removeSong = (id) => {
+        setSongs(songs.filter(song => song.id !== id));
+    };
+
+    return (
+        <div className="profile-container">
+            <h2>🎵 Canciones Guardadas</h2>
+            <div className="options">
+                <Link to="/savedSongs" className="option-button active">🎵 Canciones Guardadas</Link>
+                <Link to="/savedArtists" className="option-button">🎤 Artistas Seguidos</Link>
+            </div>
+            {songs.length === 0 ? <p>No tienes canciones guardadas.</p> : (
+                <ul>
+                    {songs.map(song => (
+                        <li key={song.id}>
+                            {song.title} - {song.artist}
+                            <button onClick={() => removeSong(song.id)}>❌</button>
+                        </li>
+                    ))}
+                </ul>
+            )}
+        </div>
+    );
+};
diff --git a/src/front/js/pages/UserProfile.js b/src/front/js/pages/UserProfile.js
new file mode 100644
index 0000000000..7e498de766
--- /dev/null
+++ b/src/front/js/pages/UserProfile.js
@@ -0,0 +1,15 @@
+import React, { useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+
+export const UserProfile = () => {
+    const navigate = useNavigate();
+
+    useEffect(() => {
+        navigate("/savedSongs"); // Redirige automáticamente a canciones guardadas
+    }, []);
+
+    return null; // No renderiza nada, solo redirige
+};
+
+export default UserProfile;
+
diff --git a/src/front/styles/index.css b/src/front/styles/index.css
index 1ac0e879a5..f8e9abc3f9 100755
--- a/src/front/styles/index.css
+++ b/src/front/styles/index.css
@@ -1,3 +1,11 @@
-/* 
-    General Styles used on every website (Don't Repeat Yourself)
-*/
+:root {
+    --color-white: #FFFFFF;
+    --color-black: #0C121C;
+    --color-red: #B80000;
+    --color-coquelicot: #FF4E2A;
+    --color-giants-orange: #FF6733;
+    --color-orange-crayola: #FF7E3C;
+    --color-atomic-tangerine: #FF914D;
+    --color-green: #00B85F;
+    --color-mauveine: #A328A3;
+}
\ No newline at end of file
diff --git a/src/front/styles/navbar.css b/src/front/styles/navbar.css
new file mode 100644
index 0000000000..873ef3845d
--- /dev/null
+++ b/src/front/styles/navbar.css
@@ -0,0 +1,62 @@
+.navbar {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 10px;
+    background: var(--color-black);
+    color: var(--color-white);
+    position: relative;
+}
+
+.navbar-brand {
+    text-decoration: none;
+    color: var(--color-white);
+    font-size: 1.5rem;
+    font-weight: bold;
+}
+
+/* Menú hamburguesa */
+.menu-icon {
+    font-size: 2rem;
+    cursor: pointer;
+    user-select: none;
+}
+
+/* Menú desplegable */
+.dropdown-menu {
+    position: absolute;
+    top: 50px;
+    right: 10px;
+    background: var(--color-white);
+    color: var(--color-black);
+    border-radius: 5px;
+    box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
+    width: 150px;
+    text-align: center;
+    padding: 10px 0;
+    opacity: 0;
+    visibility: hidden;
+    transform: translateY(-10px);
+    transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
+}
+
+/* Mostrar menú */
+.dropdown-menu.show {
+    opacity: 1;
+    visibility: visible;
+    transform: translateY(0);
+}
+
+/* Botones dentro del menú */
+.dropdown-item {
+    display: block;
+    padding: 10px;
+    text-decoration: none;
+    color: var(--color-black);
+    font-weight: bold;
+    transition: background 0.2s;
+}
+
+.dropdown-item:hover {
+    background: var(--color-atomic-tangerine);
+}
diff --git a/src/front/styles/userProfile.css b/src/front/styles/userProfile.css
new file mode 100644
index 0000000000..ebcea8e0f2
--- /dev/null
+++ b/src/front/styles/userProfile.css
@@ -0,0 +1,68 @@
+.profile-container {
+    max-width: 600px;
+    margin: auto;
+    padding: 20px;
+    text-align: center;
+    background-color: var(--color-white);
+    color: var(--color-black);
+    border-radius: 10px;
+    box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+/* Botones de navegación */
+.options {
+    display: flex;
+    justify-content: center;
+    gap: 15px;
+    margin-bottom: 20px;
+}
+
+.option-button {
+    text-decoration: none;
+    padding: 10px 15px;
+    background: var(--color-coquelicot);
+    color: var(--color-white);
+    border-radius: 5px;
+    font-weight: bold;
+    transition: background 0.3s ease;
+}
+
+.option-button:hover {
+    background: var(--color-giants-orange);
+}
+
+.option-button.active {
+    background: var(--color-black);
+    color: var(--color-white);
+}
+
+/* Lista de canciones y artistas */
+ul {
+    list-style: none;
+    padding: 0;
+}
+
+li {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10px;
+    border-bottom: 1px solid var(--color-black);
+    background: var(--color-orange-crayola);
+    border-radius: 5px;
+    margin-bottom: 5px;
+    color: var(--color-black);
+}
+
+button {
+    border: none;
+    background: var(--color-red);
+    color: var(--color-white);
+    padding: 5px 10px;
+    cursor: pointer;
+    border-radius: 5px;
+}
+
+button:hover {
+    background: var(--color-mauveine);
+}

From 17c2b388070cf06975500e619bf76fb8a033ab38 Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Mon, 24 Feb 2025 19:09:55 +0000
Subject: [PATCH 03/25] First Commit

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 80704f4378..12e3b32354 100755
--- a/.gitignore
+++ b/.gitignore
@@ -80,3 +80,4 @@ database.database
 database.db
 diagram.png
 __pycache__/
+migrations
\ No newline at end of file

From 8c469fbe0c33d19bd9d613b28d7212a9dc5b76a7 Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Mon, 24 Feb 2025 20:04:54 +0000
Subject: [PATCH 04/25] Final Commit

---
 src/front/js/pages/login.js | 111 +++++++++++++++++++++++++++++++-----
 1 file changed, 97 insertions(+), 14 deletions(-)

diff --git a/src/front/js/pages/login.js b/src/front/js/pages/login.js
index 42242866f1..b1279ff4d7 100644
--- a/src/front/js/pages/login.js
+++ b/src/front/js/pages/login.js
@@ -3,14 +3,9 @@ import "../../styles/login.css";
 import microphone from "../../img/microphone.jpg";
 
 export const Login = () => {
-  // Estado para determinar si mostramos el formulario de login o registro
+  // Estados para controlar qué formulario se muestra
   const [showLogin, setShowLogin] = useState(false);
-
-  // Función para mostrar el formulario de login
-  const showLoginForm = () => setShowLogin(true);
-
-  // Función para mostrar el formulario de registro
-  const showRegisterForm = () => setShowLogin(false);
+  const [showRegister, setShowRegister] = useState(false);
 
   return (
     <div
@@ -26,27 +21,36 @@ export const Login = () => {
     >
       <div
         className="login-container p-4 shadow-lg rounded-3 w-100"
-        style={{ maxWidth: "400px", background: "rgba(255, 255, 255, 0.5)" }}
+        style={{ maxWidth: "400px", background: "rgba(255, 255, 255, 0.8)" }}
       >
-        {!showLogin ? (
-          // Pantalla inicial con los botones
+        {/* Pantalla inicial con los botones */}
+        {!showLogin && !showRegister && (
           <div>
             <h2 className="text-center mb-4">Bienvenido</h2>
             <button
               className="btn btn-primary w-100 mb-3"
-              onClick={showLoginForm}
+              onClick={() => {
+                setShowLogin(true);
+                setShowRegister(false);
+              }}
             >
               Iniciar sesión
             </button>
+            
             <button
               className="btn btn-secondary w-100"
-              onClick={showRegisterForm}
+              onClick={() => {
+                setShowLogin(false);
+                setShowRegister(true);
+              }}
             >
               Registrarse
             </button>
           </div>
-        ) : (
-          // Formulario de login
+        )}
+
+        {/* Formulario de inicio de sesión */}
+        {showLogin && (
           <form>
             <h2 className="text-center mb-4">Iniciar sesión</h2>
             <div className="mb-3">
@@ -68,6 +72,85 @@ export const Login = () => {
             <button type="submit" className="btn btn-danger w-100 py-2">
               Ingresar
             </button>
+            <div className="text-center mt-2">
+              <a href="#" className="text-decoration-none">He olvidado mi contraseña</a>
+            </div>
+            <button
+              type="button"
+              className="btn btn-link w-100 mt-2"
+              onClick={() => setShowLogin(false)}
+            >
+              Volver
+            </button>
+          </form>
+        )}
+
+        {/* Formulario de registro */}
+        {showRegister && (
+          <form>
+            <h2 className="text-center mb-4">Registro</h2>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Nombre y apellidos"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Nombre de usuario"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="email"
+                className="form-control form-control-lg"
+                placeholder="Correo electrónico"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Dirección"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="password"
+                className="form-control form-control-lg"
+                placeholder="Contraseña"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="password"
+                className="form-control form-control-lg"
+                placeholder="Confirmar contraseña"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <label className="form-label">Subir foto de perfil</label>
+              <input type="file" className="form-control form-control-lg" />
+            </div>
+            <button type="submit" className="btn btn-success w-100 py-2">
+              Registrarse
+            </button>
+            <button
+              type="button"
+              className="btn btn-link w-100 mt-2"
+              onClick={() => setShowRegister(false)}
+            >
+              Volver
+            </button>
           </form>
         )}
       </div>

From b846874590250648c3840cfcead8ee8080a68df3 Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Tue, 25 Feb 2025 04:03:07 +0000
Subject: [PATCH 05/25] First commit

---
 src/front/js/pages/login.js | 63 ++++++++++++++++++++++++++++++-------
 1 file changed, 52 insertions(+), 11 deletions(-)

diff --git a/src/front/js/pages/login.js b/src/front/js/pages/login.js
index b1279ff4d7..5ea9811bde 100644
--- a/src/front/js/pages/login.js
+++ b/src/front/js/pages/login.js
@@ -6,6 +6,7 @@ export const Login = () => {
   // Estados para controlar qué formulario se muestra
   const [showLogin, setShowLogin] = useState(false);
   const [showRegister, setShowRegister] = useState(false);
+  const [showForgoten, setShowForgoten] = useState(false);
 
   return (
     <div
@@ -36,7 +37,7 @@ export const Login = () => {
             >
               Iniciar sesión
             </button>
-            
+
             <button
               className="btn btn-secondary w-100"
               onClick={() => {
@@ -50,7 +51,7 @@ export const Login = () => {
         )}
 
         {/* Formulario de inicio de sesión */}
-        {showLogin && (
+        {showLogin && !showForgoten && (
           <form>
             <h2 className="text-center mb-4">Iniciar sesión</h2>
             <div className="mb-3">
@@ -73,15 +74,21 @@ export const Login = () => {
               Ingresar
             </button>
             <div className="text-center mt-2">
-              <a href="#" className="text-decoration-none">He olvidado mi contraseña</a>
+              <a href="#" className="text-decoration-none" onClick={() =>
+                setShowForgoten(true)
+              }>¿He olvidado mi contraseña?</a>
+              <button
+                type="button"
+                className="btn btn-link w-100 mt-2"
+                onClick={() => {
+                  setShowForgoten(false);
+                  setShowLogin(false);
+                  setShowRegister(false)
+                }}
+              >
+                Volver
+              </button>
             </div>
-            <button
-              type="button"
-              className="btn btn-link w-100 mt-2"
-              onClick={() => setShowLogin(false)}
-            >
-              Volver
-            </button>
           </form>
         )}
 
@@ -153,7 +160,41 @@ export const Login = () => {
             </button>
           </form>
         )}
+        {/* Formulario de recuperar contraseña*/}
+        {showForgoten && (
+          <form>
+            <h2 className="text-center mb-4">¿He olvidado mi contraseña?</h2>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Nomber de usuario"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="password"
+                className="form-control form-control-lg"
+                placeholder="Nueva contraseña"
+                required
+              />
+            </div>
+            <button
+              type="button"
+              className="btn btn-link w-100 mt-2"
+              onClick={() => {
+                setShowLogin(true);
+                setShowRegister(false);
+                setShowForgoten(false)
+              }}
+            >
+              Volver
+            </button>
+          </form>)}
+
+
       </div>
-    </div>
+    </div >
   );
 };

From 01d196d418bbdf06aacd44ef33f48b9686587a3f Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Wed, 26 Feb 2025 18:32:07 +0000
Subject: [PATCH 06/25] Genre view

---
 src/front/js/layout.js      |  2 ++
 src/front/js/pages/genre.js | 69 +++++++++++++++++++++++++++++++++++++
 src/front/styles/genre.css  | 37 ++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 src/front/js/pages/genre.js
 create mode 100644 src/front/styles/genre.css

diff --git a/src/front/js/layout.js b/src/front/js/layout.js
index d135ebefc2..054b2f785b 100755
--- a/src/front/js/layout.js
+++ b/src/front/js/layout.js
@@ -12,6 +12,7 @@ import { Login } from "./pages/login";
 import { UserProfile } from "./pages/UserProfile"; // ✅ Nueva vista
 import { SavedSongs } from "./pages/SavedSongs"; // ✅ Nueva vista
 import { SavedArtists } from "./pages/SavedArtists"; // ✅ Nueva vista
+import { Genre } from "./pages/genre";
 
 import { Navbar } from "./component/navbar";
 import { Footer } from "./component/footer";
@@ -47,6 +48,7 @@ const LayoutContent = () => {
                 <Route element={<Login />} path="/login" />
                 <Route element={<Demo />} path="/demo" />
                 <Route element={<Single />} path="/single/:theid" />
+                <Route element={<Genre />} path="/genre" />
                 <Route element={<UserProfile />} path="/userProfile" />  {/* ✅ nueva */}
                 <Route element={<SavedSongs />} path="/savedSongs" />  {/* ✅ nueva */}
                 <Route element={<SavedArtists />} path="/savedArtists" />  {/* ✅ nueva */}
diff --git a/src/front/js/pages/genre.js b/src/front/js/pages/genre.js
new file mode 100644
index 0000000000..cb7a7719e1
--- /dev/null
+++ b/src/front/js/pages/genre.js
@@ -0,0 +1,69 @@
+import React, { useState } from "react";
+import { useContext } from 'react';
+import { Context } from "../store/appContext";
+import "../../styles/genre.css"
+
+export const Genre = () => {
+
+    const { store, actions } = useContext(Context);
+
+    // const newArtistFollowed = (item) => {
+    //     actions.followArtist(item)
+    // } ----- This would be with store/actions 
+
+
+    const genre = [
+        { name: 'Rock' },
+        { name: 'Pop' },
+        { name: 'Jazz' },
+
+    ]
+
+    const artist = [
+        { name: 'Artist 1', genre: 'Rock', image: 'https://placehold.co/50' },
+        { name: 'Artist 2', genre: 'Rock', image: 'https://placehold.co/50' },
+
+        { name: 'Artist 3', genre: 'Pop', image: 'https://placehold.co/50' },
+        { name: 'Artist 4', genre: 'Pop', image: 'https://placehold.co/50' },
+
+        { name: 'Artist 5', genre: 'Jazz', image: 'https://placehold.co/50' },
+        { name: 'Artist 6', genre: 'Jazz', image: 'https://placehold.co/50' },
+        // More artists...
+    ]
+
+
+    return (
+        <div className="container">
+
+            {genre?.map((g, index) => {
+                return (
+                    <div key={index}>
+                        <h1 className="genretitle mt-3">{g.name}</h1><br />
+                        <div className="artists row row-cols-1 row-cols-md-3 g-4">
+
+                            {artist?.map((artist, artistIndex) => {
+
+                                return (
+                                    <div key={artistIndex} className="artistcard">
+                                        <div className="card">
+                                            <img src={artist.image} className="card-img-top" alt={artist.name} />
+                                            <div className="card-body">
+                                                <h5 className="card-title">{artist.name}</h5>
+                                            </div>
+                                            <div className="d-flex justify-content-center mb-3">
+                                                <button type="button" className="followbtn btn-outline-purple">
+                                                    {/* onClick={() => newArtistFollowed(artist.name)} */}
+                                                    Follow artist
+                                                </button>
+                                            </div>
+                                        </div>
+                                    </div>
+                                );
+                            })}
+                        </div>
+                    </div>
+                );
+            })}
+        </div>
+    )
+}
diff --git a/src/front/styles/genre.css b/src/front/styles/genre.css
new file mode 100644
index 0000000000..7e3d222293
--- /dev/null
+++ b/src/front/styles/genre.css
@@ -0,0 +1,37 @@
+.genretitle {
+    display: flex;
+    justify-content: start;
+    color: var(--color-mauveine);
+}
+
+.artists {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: nowrap;
+    overflow-x: auto;
+    gap: 16px;
+    padding: 10px;
+    scrollbar-width: thin;
+}
+
+.artistcard {
+    width: 20%;
+    background-color: rgba(97, 235, 97, 0.641);
+}
+
+.followbtn {
+    background-color: transparent;
+    color: var(--color-mauveine);
+    border: 2px solid var(--color-mauveine);
+    padding: 10px 20px;
+    font-size: 16px;
+    border-radius: 5px;
+    transition: all 0.3s ease-in-out;
+    cursor: pointer;
+}
+
+.btn-outline-purple:hover {
+    background-color: var(--color-mauveine);
+    color: white;
+}
+

From 81bcd48a184fc14a4ac8aa35f0b260b1b59e2b57 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Wed, 26 Feb 2025 19:48:20 +0000
Subject: [PATCH 07/25] Genre view modified

---
 src/front/js/pages/genre.js | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/front/js/pages/genre.js b/src/front/js/pages/genre.js
index cb7a7719e1..e366466cd7 100644
--- a/src/front/js/pages/genre.js
+++ b/src/front/js/pages/genre.js
@@ -20,14 +20,14 @@ export const Genre = () => {
     ]
 
     const artist = [
-        { name: 'Artist 1', genre: 'Rock', image: 'https://placehold.co/50' },
-        { name: 'Artist 2', genre: 'Rock', image: 'https://placehold.co/50' },
+        { name: 'Artista 1', genre: 'Rock', image: 'https://placehold.co/50' },
+        { name: 'Artista 2', genre: 'Rock', image: 'https://placehold.co/50' },
 
-        { name: 'Artist 3', genre: 'Pop', image: 'https://placehold.co/50' },
-        { name: 'Artist 4', genre: 'Pop', image: 'https://placehold.co/50' },
+        { name: 'Artista 3', genre: 'Pop', image: 'https://placehold.co/50' },
+        { name: 'Artista 4', genre: 'Pop', image: 'https://placehold.co/50' },
 
-        { name: 'Artist 5', genre: 'Jazz', image: 'https://placehold.co/50' },
-        { name: 'Artist 6', genre: 'Jazz', image: 'https://placehold.co/50' },
+        { name: 'Artista 5', genre: 'Jazz', image: 'https://placehold.co/50' },
+        { name: 'Artista 6', genre: 'Jazz', image: 'https://placehold.co/50' },
         // More artists...
     ]
 
@@ -53,7 +53,7 @@ export const Genre = () => {
                                             <div className="d-flex justify-content-center mb-3">
                                                 <button type="button" className="followbtn btn-outline-purple">
                                                     {/* onClick={() => newArtistFollowed(artist.name)} */}
-                                                    Follow artist
+                                                    Seguir artista
                                                 </button>
                                             </div>
                                         </div>

From de770815c8f9e97ae7d9352e5b6a4f305fd6aa47 Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Sun, 2 Mar 2025 03:11:18 +0000
Subject: [PATCH 08/25] cambios en login, creacion user/artist data

---
 src/front/js/layout.js           |   4 +
 src/front/js/pages/ArtistData.js | 131 +++++++++++++++++++++++++++++++
 src/front/js/pages/UserData.js   | 131 +++++++++++++++++++++++++++++++
 src/front/js/pages/login.js      |   2 +-
 src/front/styles/data.css        |  25 ++++++
 src/front/styles/login.css       |  12 ++-
 6 files changed, 297 insertions(+), 8 deletions(-)
 create mode 100644 src/front/js/pages/ArtistData.js
 create mode 100644 src/front/js/pages/UserData.js
 create mode 100644 src/front/styles/data.css

diff --git a/src/front/js/layout.js b/src/front/js/layout.js
index d135ebefc2..649e521ca0 100755
--- a/src/front/js/layout.js
+++ b/src/front/js/layout.js
@@ -12,6 +12,8 @@ import { Login } from "./pages/login";
 import { UserProfile } from "./pages/UserProfile"; // ✅ Nueva vista
 import { SavedSongs } from "./pages/SavedSongs"; // ✅ Nueva vista
 import { SavedArtists } from "./pages/SavedArtists"; // ✅ Nueva vista
+import { UserData } from "./pages/UserData"
+import { ArtistData } from "./pages/ArtistData"
 
 import { Navbar } from "./component/navbar";
 import { Footer } from "./component/footer";
@@ -50,6 +52,8 @@ const LayoutContent = () => {
                 <Route element={<UserProfile />} path="/userProfile" />  {/* ✅ nueva */}
                 <Route element={<SavedSongs />} path="/savedSongs" />  {/* ✅ nueva */}
                 <Route element={<SavedArtists />} path="/savedArtists" />  {/* ✅ nueva */}
+                <Route element={<UserData />} path="/userData" />
+                <Route element={<ArtistData />} path="/artistData" />
                 <Route element={<h1>Not found!</h1>} />
             </Routes>
 
diff --git a/src/front/js/pages/ArtistData.js b/src/front/js/pages/ArtistData.js
new file mode 100644
index 0000000000..b701e93460
--- /dev/null
+++ b/src/front/js/pages/ArtistData.js
@@ -0,0 +1,131 @@
+import React, { useState } from "react";
+import "../../styles/data.css"
+import Imagen from "../../img/microphone.jpg";  // Asegúrate de que la ruta sea correcta
+
+export const ArtistData = () => {
+    const [showEditData, setShowEditData] = useState(false);
+
+    const clickEditData = () => {
+        setShowEditData(true);
+    };
+
+    const cancelEditData = (event) => {
+        event.preventDefault();  // Prevenir el comportamiento por defecto
+        setShowEditData(false);
+    };
+
+    return (
+        <div className="container mt-4">
+            <div className="card p-4 d-flex flex-row align-items-center justify-content-between" style={{ maxWidth: "100%", minHeight: "220px" }}>
+                {/* Información del usuario (Izquierda) */}
+                <div className="card-body">
+                    <h1 className="card-title text-white">Nombre del Usuario</h1>
+                </div>
+
+                {/* Imagen del usuario + Botón (Derecha) */}
+                <div className="d-flex flex-column align-items-center" style={{ paddingRight: "20px" }}>
+                    <div style={{ width: "140px", height: "140px", overflow: "hidden", borderRadius: "50%" }}>
+                        <img
+                            src={Imagen}
+                            className="img-fluid"
+                            alt="Foto de perfil"
+                            style={{ width: "100%", height: "100%", objectFit: "cover" }}
+                        />
+                    </div>
+                    <button className=" btn btn-success mt-3 boton" style={{ marginBottom: "10px" }}>Editar Foto</button>
+                </div>
+            </div>
+
+            {!showEditData && (
+                <div className="card bg-white mt-3">
+                    <h2 className="card-header">Datos Personales</h2>
+                    <div className="card-body">
+                        <h4 className="card-title mb-1">Correo</h4>
+                        <p className="card-text mb-3">asdasdasdas@gmail.com</p>
+                        <h4 className="card-title mb-1">Nombre y apellidos</h4>
+                        <p className="card-text mb-3">Pepito diaz</p>
+                        <h4 className="card-title mb-1">Direccion</h4>
+                        <p className="card-text mb-3">Calle de la piruleta 123</p>
+                        <h4 className="card-title mb-1">Telefono</h4>
+                        <p className="card-text mb-3">666666666</p>
+                        <h4 className="card-title mb-1">Artista</h4>
+                        <p className="card-text mb-3">Si</p>
+                        <div className="d-flex justify-content-end">
+                            <button className="btn btn-success boton mt-3 boton" style={{ marginBottom: "10px" }} onClick={clickEditData}>
+                                Editar Perfil
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            )}
+
+            {showEditData && (
+                <form className="mt-4 text-white">
+                    <h1 className="text-center mb-4 text-white">Editar Datos</h1>
+                    <div className="mb-3">
+                        <label>Email</label>
+                        <input
+                            type="text"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Nombre de usuario</label>
+                        <input
+                            type="text"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Contraseña</label>
+                        <input
+                            type="password"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Repite Contraseña</label>
+                        <input
+                            type="password"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Dirección</label>
+                        <input
+                            type="text"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Teléfono</label>
+                        <input
+                            type="number"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="d-flex col-md-12 justify-content-center">
+                        <button type="submit" className="btn btn-danger py-2 col-md-3 me-2">
+                            Guardar
+                        </button>
+                        <button type="button" className="btn btn-danger py-2 col-md-3 ms-2" onClick={cancelEditData}>
+                            Volver
+                        </button>
+                    </div>
+                </form>
+            )}
+        </div>
+    );
+};
diff --git a/src/front/js/pages/UserData.js b/src/front/js/pages/UserData.js
new file mode 100644
index 0000000000..28cb0892dc
--- /dev/null
+++ b/src/front/js/pages/UserData.js
@@ -0,0 +1,131 @@
+import React, { useState } from "react";
+import "../../styles/data.css"
+import Imagen from "../../img/microphone.jpg";  // Asegúrate de que la ruta sea correcta
+
+export const UserData = () => {
+    const [showEditData, setShowEditData] = useState(false);
+
+    const clickEditData = () => {
+        setShowEditData(true);
+    };
+
+    const cancelEditData = (event) => {
+        event.preventDefault();  // Prevenir el comportamiento por defecto
+        setShowEditData(false);
+    };
+
+    return (
+        <div className="container mt-4">
+            <div className="card p-4 d-flex flex-row align-items-center justify-content-between" style={{ maxWidth: "100%", minHeight: "220px" }}>
+                {/* Información del usuario (Izquierda) */}
+                <div className="card-body">
+                    <h1 className="card-title text-white">Nombre del Usuario</h1>
+                </div>
+
+                {/* Imagen del usuario + Botón (Derecha) */}
+                <div className="d-flex flex-column align-items-center" style={{ paddingRight: "20px" }}>
+                    <div style={{ width: "140px", height: "140px", overflow: "hidden", borderRadius: "50%" }}>
+                        <img
+                            src={Imagen}
+                            className="img-fluid"
+                            alt="Foto de perfil"
+                            style={{ width: "100%", height: "100%", objectFit: "cover" }}
+                        />
+                    </div>
+                    <button className=" boton btn btn-danger mt-3" style={{ marginBottom: "10px" }}>Editar Foto</button>
+                </div>
+            </div>
+
+            {!showEditData && (
+                <div className="card bg-white mt-3">
+                    <h2 className="card-header">Datos Personales</h2>
+                    <div className="card-body">
+                        <h4 className="card-title mb-1">Correo</h4>
+                        <p className="card-text mb-3">asdasdasdas@gmail.com</p>
+                        <h4 className="card-title mb-1">Nombre y apellidos</h4>
+                        <p className="card-text mb-3">Pepito diaz</p>
+                        <h4 className="card-title mb-1">Direccion</h4>
+                        <p className="card-text mb-3">Calle de la piruleta 123</p>
+                        <h4 className="card-title mb-1">Telefono</h4>
+                        <p className="card-text mb-3">666666666</p>
+                        <h4 className="card-title mb-1">Artista</h4>
+                        <p className="card-text mb-3">No</p>
+                        <div className="d-flex justify-content-end">
+                            <button className="btn btn-danger mt-3" style={{ marginBottom: "10px" }} onClick={clickEditData}>
+                                Editar Perfil
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            )}
+
+            {showEditData && (
+                <form className="mt-4">
+                    <h1 className="text-center mb-4 text-white">Editar Datos</h1>
+                    <div className="mb-3">
+                        <label>Email</label>
+                        <input
+                            type="text"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Nombre de usuario</label>
+                        <input
+                            type="text"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Contraseña</label>
+                        <input
+                            type="password"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Repite Contraseña</label>
+                        <input
+                            type="password"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Dirección</label>
+                        <input
+                            type="text"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="mb-3">
+                        <label>Teléfono</label>
+                        <input
+                            type="number"
+                            className="form-control form-control-lg"
+                            placeholder=""
+                            required
+                        />
+                    </div>
+                    <div className="d-flex col-md-12 justify-content-center">
+                        <button type="submit" className="btn btn-danger py-2 col-md-3 me-2">
+                            Guardar
+                        </button>
+                        <button type="button" className="btn btn-danger py-2 col-md-3 ms-2" onClick={cancelEditData}>
+                            Volver
+                        </button>
+                    </div>
+                </form>
+            )}
+        </div>
+    );
+};
diff --git a/src/front/js/pages/login.js b/src/front/js/pages/login.js
index 5ea9811bde..5c52ced40f 100644
--- a/src/front/js/pages/login.js
+++ b/src/front/js/pages/login.js
@@ -29,7 +29,7 @@ export const Login = () => {
           <div>
             <h2 className="text-center mb-4">Bienvenido</h2>
             <button
-              className="btn btn-primary w-100 mb-3"
+              className="btn btn-danger boton w-100 mb-3"
               onClick={() => {
                 setShowLogin(true);
                 setShowRegister(false);
diff --git a/src/front/styles/data.css b/src/front/styles/data.css
new file mode 100644
index 0000000000..0696b85baa
--- /dev/null
+++ b/src/front/styles/data.css
@@ -0,0 +1,25 @@
+body {
+    background-color: #0C121C; /* Color oscuro de fondo */
+    color: #0C121C;; /* Texto en blanco para mejor visibilidad */
+    font-family: Arial, sans-serif; /* Fuente legible */
+    margin: 0;
+    padding: 0;
+}
+
+.card{
+    background-color:rgba(163, 40, 163, 0.5); /* 50% de opacidad */
+    
+}
+
+/*.boton{
+    background: linear-gradient(135deg, #b80000, #ff4e2a, #ff6733, #ff7e3c, #ff914d);
+}
+
+.boton:hover{
+    background: linear-gradient(135deg, 
+    rgba(184, 0, 0, 0.75), 
+    rgba(255, 78, 42, 0.75), 
+    rgba(255, 103, 51, 0.75), 
+    rgba(255, 126, 60, 0.75), 
+    rgba(255, 145, 77, 0.75));
+}*/
\ No newline at end of file
diff --git a/src/front/styles/login.css b/src/front/styles/login.css
index 342737402e..a97e5788eb 100644
--- a/src/front/styles/login.css
+++ b/src/front/styles/login.css
@@ -1,7 +1,5 @@
-.red {
-    background: url(../img/microphone.jpg);
-    background-size: cover;
-    background-repeat: no-repeat;
-    margin: 0;
-    height: 100vh;
-  }
\ No newline at end of file
+
+
+  /*.boton{
+    background: linear-gradient(135deg, #b80000, #ff4e2a, #ff6733, #ff7e3c, #ff914d);
+}*/
\ No newline at end of file

From 62b7ab703f51bdca73b7a09c8cdca298d9fd6e84 Mon Sep 17 00:00:00 2001
From: Jaime BP <jaimebernet@gmail.com>
Date: Mon, 3 Mar 2025 17:52:01 +0000
Subject: [PATCH 09/25] 1commit

---
 src/api/routes.py                   |  21 ++++
 src/front/js/component/navbar.js    |  10 +-
 src/front/js/layout.js              |   2 +
 src/front/js/pages/ArtistBio.js     |  13 +++
 src/front/js/pages/ArtistImages.js  |  72 ++++++++++++++
 src/front/js/pages/ArtistMusic.js   |  39 ++++++++
 src/front/js/pages/ArtistProfile.js | 139 ++++++++++++++++++++++++++
 src/front/js/pages/ArtistVideos.js  |  31 ++++++
 src/front/styles/artistProfile.css  | 147 ++++++++++++++++++++++++++++
 src/front/styles/navbar.css         |  33 +++++--
 10 files changed, 494 insertions(+), 13 deletions(-)
 create mode 100644 src/front/js/pages/ArtistBio.js
 create mode 100644 src/front/js/pages/ArtistImages.js
 create mode 100644 src/front/js/pages/ArtistMusic.js
 create mode 100644 src/front/js/pages/ArtistProfile.js
 create mode 100644 src/front/js/pages/ArtistVideos.js
 create mode 100644 src/front/styles/artistProfile.css

diff --git a/src/api/routes.py b/src/api/routes.py
index 029589a3a1..9e463890c3 100644
--- a/src/api/routes.py
+++ b/src/api/routes.py
@@ -5,12 +5,26 @@
 from api.models import db, User
 from api.utils import generate_sitemap, APIException
 from flask_cors import CORS
+import os
+
+# Import the Cloudinary libraries
+# ==============================
+import cloudinary
+from cloudinary import CloudinaryImage
+import cloudinary.uploader
+import cloudinary.api
 
 api = Blueprint('api', __name__)
 
 # Allow CORS requests to this API
 CORS(api)
 
+cloudinary.config(
+    cloud_name= os.getenv('CLOUD_NAME'),
+    api_key= os.getenv('CLOUDINARY_API_KEY'),
+    api_secret= os.getenv('CLOUDINARY_API_SECRET'),
+    secure= True
+)
 
 @api.route('/hello', methods=['POST', 'GET'])
 def handle_hello():
@@ -20,3 +34,10 @@ def handle_hello():
     }
 
     return jsonify(response_body), 200
+
+@api.route('/img', methods=["POST"])
+def upload_image():
+    img = request.files["img"]
+    img_url = cloudinary.uploader.upload(img)
+    print(img_url)
+    return jsonify({"img": img_url["url"]}),200
\ No newline at end of file
diff --git a/src/front/js/component/navbar.js b/src/front/js/component/navbar.js
index 3be878d86e..8837c3fcdc 100755
--- a/src/front/js/component/navbar.js
+++ b/src/front/js/component/navbar.js
@@ -12,11 +12,12 @@ export const Navbar = () => {
     return (
         <nav className="navbar">
             <div className="container">
-                <Link to="/" className="navbar-brand">SoundCript</Link>
+                <Link to="/"  className="navbar-brand">SoundCript</Link>
 
-                {/* Botón de menú hamburguesa */}
-                <div className="menu-icon" onClick={toggleMenu}>
-                    ☰
+                {/* Icono de usuario (imagen por defecto) */}
+                <div className="user-menu">
+                <div className="user-icon" onClick={toggleMenu}>
+                    <img src="https://cdn-icons-png.flaticon.com/512/3106/3106921.png" alt="Perfil de Usuario" />
                 </div>
 
                 {/* Menú desplegable */}
@@ -24,6 +25,7 @@ export const Navbar = () => {
                     <Link to="/userProfile" className="dropdown-item" onClick={() => setMenuOpen(false)}>Perfil</Link>
                     <Link to="/logout" className="dropdown-item" onClick={() => setMenuOpen(false)}>Logout</Link>
                 </div>
+                </div>
             </div>
         </nav>
     );
diff --git a/src/front/js/layout.js b/src/front/js/layout.js
index d135ebefc2..fe1d29f2ee 100755
--- a/src/front/js/layout.js
+++ b/src/front/js/layout.js
@@ -12,6 +12,7 @@ import { Login } from "./pages/login";
 import { UserProfile } from "./pages/UserProfile"; // ✅ Nueva vista
 import { SavedSongs } from "./pages/SavedSongs"; // ✅ Nueva vista
 import { SavedArtists } from "./pages/SavedArtists"; // ✅ Nueva vista
+import ArtistProfile from "./pages/ArtistProfile";
 
 import { Navbar } from "./component/navbar";
 import { Footer } from "./component/footer";
@@ -50,6 +51,7 @@ const LayoutContent = () => {
                 <Route element={<UserProfile />} path="/userProfile" />  {/* ✅ nueva */}
                 <Route element={<SavedSongs />} path="/savedSongs" />  {/* ✅ nueva */}
                 <Route element={<SavedArtists />} path="/savedArtists" />  {/* ✅ nueva */}
+                <Route element={<ArtistProfile />} path="/artist/:artistId" /> {/* ultima */}
                 <Route element={<h1>Not found!</h1>} />
             </Routes>
 
diff --git a/src/front/js/pages/ArtistBio.js b/src/front/js/pages/ArtistBio.js
new file mode 100644
index 0000000000..a78feb7676
--- /dev/null
+++ b/src/front/js/pages/ArtistBio.js
@@ -0,0 +1,13 @@
+import React from "react";
+
+const ArtistBio = ({ artistData }) => {
+    return (
+        <div>
+            <h2>Biografía</h2>
+            <p>{artistData.biography}</p>
+            {/* Aqui irá el botón para editar la bio si eres el dueño del perfil */}
+        </div>
+    );
+};
+
+export default ArtistBio;
diff --git a/src/front/js/pages/ArtistImages.js b/src/front/js/pages/ArtistImages.js
new file mode 100644
index 0000000000..0b27e9bccd
--- /dev/null
+++ b/src/front/js/pages/ArtistImages.js
@@ -0,0 +1,72 @@
+import React, { useState, useEffect } from "react";
+
+const ArtistImages = ({ artistData }) => {
+  const [file, setFile] = useState(null);
+  const [fileUrl, setFileUrl] = useState("");
+
+  // Función para actualizar el archivo seleccionado
+  const handleImgChange = (e) => {
+    if (e.target.files && e.target.files.length) {
+      setFile(e.target.files[0]);
+    }
+  };
+
+  // Función para enviar el archivo al backend
+  const sendFile = async () => {
+    if (!file) {
+      alert("El campo de imagen es obligatorio");
+      return;
+    }
+    try {
+      const form = new FormData();
+      form.append("img", file);
+
+      const response = await fetch(`${process.env.BACKEND_URL}/api/img`, {
+        method: "POST",
+        body: form,
+      });
+      console.log(response);
+      const data = await response.json();
+      setFileUrl(data.img);
+    } catch (error) {
+      console.error("Error al subir la imagen:", error);
+    }
+  };
+
+  return (
+    <div>
+      <h2>Imágenes</h2>
+      {artistData.images && artistData.images.length > 0 ? (
+        <div className="images-container">
+          {artistData.images.map((imgUrl, index) => (
+            <img key={index} src={imgUrl} alt={`Imagen ${index}`} />
+          ))}
+        </div>
+      ) : (
+        <p>No hay imágenes disponibles.</p>
+      )}
+      {/* Cuadro para subir imágenes */}
+      <div className="row m-5 bg-secondary bg-opacity-10 p-2">
+        <div className="col-12 mb-3">
+          <h4 className="m-2">Subir Imagen (Cloudinary)</h4>
+          <input
+            type="file"
+            className="form-control mb-2"
+            accept="image/jpeg"
+            onChange={handleImgChange}
+          />
+          <button className="btn btn-primary" onClick={sendFile}>
+            Send
+          </button>
+        </div>
+        {fileUrl !== "" ? (
+          <div className="col-4">
+            <img src={fileUrl} className="w-100 h-100" alt="Uploaded" />
+          </div>
+        ) : null}
+      </div>
+    </div>
+  );
+};
+
+export default ArtistImages;
diff --git a/src/front/js/pages/ArtistMusic.js b/src/front/js/pages/ArtistMusic.js
new file mode 100644
index 0000000000..522bca2f48
--- /dev/null
+++ b/src/front/js/pages/ArtistMusic.js
@@ -0,0 +1,39 @@
+// ArtistMusic.js
+import React from "react";
+import "../../styles/artistProfile.css";
+
+const ArtistMusic = ({ artistData }) => {
+    // Aquí podemos implementar la lógica para manejar el "like"
+    const handleLike = (trackId) => {
+        console.log("Liked track:", trackId);
+        // Aquí llamamos a la API o actualizamos el estado
+    };
+
+    return (
+        <div>
+            <h2>Música</h2>
+            {artistData.music && artistData.music.length > 0 ? (
+                <ul className="song-list">
+                    {artistData.music.map((track) => (
+                        <li key={track.id} className="song-item">
+                            <span>
+                                <strong>{track.title}</strong>
+                            </span>
+                            <button
+                                className="like-button"
+                                onClick={() => handleLike(track.id)}
+                            >
+                                👍 Like
+                            </button>
+                        </li>
+                    ))}
+                </ul>
+            ) : (
+                <p>No hay canciones disponibles.</p>
+            )}
+            {/* Aqui irá el botón para subir canciones si eres el dueño del perfil */}
+        </div>
+    );
+};
+
+export default ArtistMusic;
diff --git a/src/front/js/pages/ArtistProfile.js b/src/front/js/pages/ArtistProfile.js
new file mode 100644
index 0000000000..047f524733
--- /dev/null
+++ b/src/front/js/pages/ArtistProfile.js
@@ -0,0 +1,139 @@
+// ArtistProfile.js
+import React, { useState, useEffect } from "react";
+import { useParams } from "react-router-dom";
+import ArtistBio from "./ArtistBio";
+import ArtistImages from "./ArtistImages";
+import ArtistVideos from "./ArtistVideos";
+import ArtistMusic from "./ArtistMusic";
+import "../../styles/artistProfile.css";
+
+const ArtistProfile = () => {
+    const { artistId } = useParams();
+    const [activeTab, setActiveTab] = useState("bio");
+    const [artistData, setArtistData] = useState(null);
+    const [loading, setLoading] = useState(true);
+    const [error, setError] = useState(null);
+
+    useEffect(() => {
+        const fetchArtistData = async () => {
+            try {
+                // Simula una llamada a la API
+                const data = {
+                    id: artistId,
+                    name: "Artist Example",
+                    profilePicture: "https://placehold.co/600x400",
+                    biography: "Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...Esta es la biografía de ejemplo del artista...",
+                    images: ["https://placehold.co/300", "https://placehold.co/300"],
+                    videos: ["https://www.youtube.com/embed/VIDEO_ID"],
+                    music: [
+                        { id: 1, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 2, title: "Canción 2", url: "https://placehold.co/audio2" },
+                        { id: 3, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 4, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 5, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 6, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 7, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 8, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 9, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 10, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 11, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 12, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 13, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 14, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 15, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 16, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 17, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 18, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 19, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 20, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 21, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 22, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 23, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 24, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 25, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 26, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 27, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 28, title: "Canción 1", url: "https://placehold.co/audio1" },
+                        { id: 29, title: "Canción 1", url: "https://placehold.co/audio1" }
+
+                    ]
+                };
+                setArtistData(data);
+                setLoading(false);
+            } catch (err) {
+                setError("Error al cargar los datos del artista.");
+                setLoading(false);
+            }
+        };
+
+        fetchArtistData();
+    }, [artistId]);
+
+    if (loading) return <p>Cargando...</p>;
+    if (error) return <p>{error}</p>;
+
+    const handleTabChange = (tab) => setActiveTab(tab);
+
+    // Lógica para seguir al artista (ejemplo simple)
+    const handleFollow = () => {
+        console.log("Siguiendo al artista:", artistData.id);
+        // Aquí implementas la lógica de seguir (API, estado, etc.)
+    };
+
+    return (
+        <div className="artist-profile-container">
+            {/* Encabezado del perfil */}
+            <div className="artist-header">
+                <div className="artist-img-container">
+                    <img
+                        src={artistData.profilePicture}
+                        alt="Artist"
+                        className="artist-profile-picture"
+                    />
+                    <button className="follow-button" onClick={handleFollow}>
+                        Seguir
+                    </button>
+                </div>
+                <h1>{artistData.name}</h1>
+            </div>
+
+            {/* Menú de pestañas */}
+            <div className="artist-tabs">
+                <button
+                    className={activeTab === "bio" ? "active" : ""}
+                    onClick={() => handleTabChange("bio")}
+                >
+                    Biografía
+                </button>
+                <button
+                    className={activeTab === "images" ? "active" : ""}
+                    onClick={() => handleTabChange("images")}
+                >
+                    Imágenes
+                </button>
+                <button
+                    className={activeTab === "videos" ? "active" : ""}
+                    onClick={() => handleTabChange("videos")}
+                >
+                    Vídeos
+                </button>
+                <button
+                    className={activeTab === "music" ? "active" : ""}
+                    onClick={() => handleTabChange("music")}
+                >
+                    Música
+                </button>
+            </div>
+
+            {/* Contenido de la pestaña activa */}
+            <div className="artist-content">
+                {activeTab === "bio" && <ArtistBio artistData={artistData} />}
+                {activeTab === "images" && <ArtistImages artistData={artistData} />}
+                {activeTab === "videos" && <ArtistVideos artistData={artistData} />}
+                {activeTab === "music" && <ArtistMusic artistData={artistData} />}
+            </div>
+        </div>
+    );
+};
+
+export default ArtistProfile;
diff --git a/src/front/js/pages/ArtistVideos.js b/src/front/js/pages/ArtistVideos.js
new file mode 100644
index 0000000000..c7bb343fc2
--- /dev/null
+++ b/src/front/js/pages/ArtistVideos.js
@@ -0,0 +1,31 @@
+import React from "react";
+
+const ArtistVideos = ({ artistData }) => {
+    return (
+        <div>
+            <h2>Vídeos</h2>
+            {artistData.videos && artistData.videos.length > 0 ? (
+                <div className="videos-container">
+                    {artistData.videos.map((videoUrl, index) => (
+                        <div key={index} className="video-wrapper">
+                            <iframe
+                                width="560"
+                                height="315"
+                                src={videoUrl}
+                                title={`Video ${index}`}
+                                frameBorder="0"
+                                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
+                                allowFullScreen
+                            ></iframe>
+                        </div>
+                    ))}
+                </div>
+            ) : (
+                <p>No hay vídeos disponibles.</p>
+            )}
+            {/* Aqui irá el botón para subir vídeos si eres el dueño del perfil */}
+        </div>
+    );
+};
+
+export default ArtistVideos;
diff --git a/src/front/styles/artistProfile.css b/src/front/styles/artistProfile.css
new file mode 100644
index 0000000000..04678a93d9
--- /dev/null
+++ b/src/front/styles/artistProfile.css
@@ -0,0 +1,147 @@
+.artist-profile-container {
+    max-width: 800px;
+    margin: 20px auto;
+    background-color: var(--color-white);
+    color: var(--color-black);
+    border-radius: 10px;
+    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+    padding: 20px;
+  }
+  
+  .artist-header {
+    display: flex;
+    align-items: center;
+    position: relative;
+    gap: 20px;
+    margin-bottom: 20px;
+  }
+  .artist-header h1 {
+    margin: 80px;  /* Empuja el texto al centro */
+  }
+  
+  .artist-profile-picture {
+    width: 150px;
+    height: 150px;
+    object-fit: cover;
+    border-radius: 50%;
+  }
+  
+  .artist-tabs {
+    display: flex;
+    gap: 10px;
+    margin-bottom: 20px;
+    justify-content: center;
+  }
+  
+  .artist-tabs button {
+    padding: 10px 20px;
+    background: var(--color-coquelicot);
+    color: var(--color-white);
+    border: none;
+    border-radius: 5px;
+    cursor: pointer;
+    font-weight: bold;
+    transition: background 0.3s;
+  }
+  
+  .artist-tabs button:hover {
+    background: var(--color-giants-orange);
+  }
+  
+  .artist-tabs button.active {
+    background: var(--color-black);
+  }
+  
+  .artist-content {
+    text-align: center;
+  }
+  
+  .images-container {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 10px;
+    justify-content: center;
+  }
+  
+  .images-container img {
+    max-width: 300px;
+    border-radius: 5px;
+  }
+  
+  .videos-container {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 10px;
+    justify-content: center;
+  }
+  
+  .video-wrapper {
+    width: 560px;
+    max-width: 100%;
+    margin-bottom: 10px;
+  }
+  
+  ul {
+    list-style: none;
+    padding: 0;
+  }
+  
+  li {
+    background: var(--color-orange-crayola);
+    margin: 10px 0;
+    padding: 10px;
+    border-radius: 5px;
+  }
+  
+  .song-list {
+    list-style: none;
+    padding: 0;
+  }
+  
+  .song-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10px;
+    border-bottom: 1px solid var(--color-black);
+    background: var(--color-orange-crayola);
+    border-radius: 5px;
+    margin-bottom: 5px;
+  }
+  
+  .like-button {
+    background: var(--color-green);
+    color: var(--color-white);
+    border: none;
+    padding: 5px 10px;
+    border-radius: 5px;
+    cursor: pointer;
+    transition: background 0.3s ease;
+  }
+  
+  .like-button:hover {
+    background: var(--color-mauveine);
+  }
+  
+
+  .artist-img-container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+  }
+  
+  .follow-button {
+    margin-top: 10px;
+    background: var(--color-green);
+    color: var(--color-white);
+    border: none;
+    padding: 5px 10px;
+    border-radius: 5px;
+    cursor: pointer;
+    transition: background 0.3s ease;
+  }
+  
+  .follow-button:hover {
+    background: var(--color-giants-orange);
+  }
+  
\ No newline at end of file
diff --git a/src/front/styles/navbar.css b/src/front/styles/navbar.css
index 873ef3845d..a893ea098b 100644
--- a/src/front/styles/navbar.css
+++ b/src/front/styles/navbar.css
@@ -1,13 +1,25 @@
 .navbar {
+    margin-top: 15px;
     display: flex;
-    justify-content: space-between;
     align-items: center;
-    padding: 10px;
-    background: var(--color-black);
+    justify-content: space-between;
+    /* Ejemplo de degradado desde rojo hasta atomic-tangerine */
+    background: linear-gradient(
+        90deg, 
+        var(--color-red) 0%, 
+        var(--color-giants-orange) 50%, 
+        var(--color-atomic-tangerine) 100%
+    );
     color: var(--color-white);
+    padding: 10px 20px;
+    border-radius: 30px; /* Para darle bordes redondeados */
     position: relative;
 }
 
+.user-menu {
+    position: relative; /* Esto hace que cualquier elemento con posición absoluta se posicione relativo a este contenedor */
+}
+
 .navbar-brand {
     text-decoration: none;
     color: var(--color-white);
@@ -15,18 +27,21 @@
     font-weight: bold;
 }
 
-/* Menú hamburguesa */
-.menu-icon {
-    font-size: 2rem;
+
+.user-icon img {
+    width: 40px;            
+    height: 40px;
+    border-radius: 50%;    
+    object-fit: cover;      
     cursor: pointer;
-    user-select: none;
 }
 
+
 /* Menú desplegable */
 .dropdown-menu {
     position: absolute;
-    top: 50px;
-    right: 10px;
+    top: 100%;
+    right: 1;  
     background: var(--color-white);
     color: var(--color-black);
     border-radius: 5px;

From 1090fa75c62f617771236ee8c3db6c31f4c0b3b6 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Wed, 5 Mar 2025 15:44:05 +0000
Subject: [PATCH 10/25] Load Genres API

---
 Pipfile                              |   1 +
 Pipfile.lock                         | 130 +++++++++++++++++++++++++--
 migrations/versions/22b5bf5541c4_.py |  35 --------
 migrations/versions/34a3df02bba3_.py |  35 --------
 src/api/admin.py                     |   3 +-
 src/api/models.py                    |  14 +++
 src/api/routes.py                    |  26 +++++-
 src/front/js/pages/genre.js          |  12 ++-
 src/front/js/store/flux.js           |  28 +++++-
 9 files changed, 192 insertions(+), 92 deletions(-)
 delete mode 100644 migrations/versions/22b5bf5541c4_.py
 delete mode 100644 migrations/versions/34a3df02bba3_.py

diff --git a/Pipfile b/Pipfile
index b461e2e4ee..78ccb678b4 100644
--- a/Pipfile
+++ b/Pipfile
@@ -20,6 +20,7 @@ flask-admin = "*"
 typing-extensions = "*"
 flask-jwt-extended = "==4.6.0"
 wtforms = "==3.1.2"
+requests = "*"
 
 [requires]
 python_version = "3.10"
diff --git a/Pipfile.lock b/Pipfile.lock
index 508225b0a1..02f73eb510 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "4f0e9a772f04b621ff0313b7ecfa468af1526aa27df8bfcacac6955d499d352d"
+            "sha256": "565f98e9600186b666ea99818452df31f2af6834fd198eaf1fcc557fed5d866b"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -18,11 +18,11 @@
     "default": {
         "alembic": {
             "hashes": [
-                "sha256:1acdd7a3a478e208b0503cd73614d5e4c6efafa4e73518bb60e4f2846a37b1c5",
-                "sha256:496e888245a53adf1498fcab31713a469c65836f8de76e01399aa1c3e90dd213"
+                "sha256:197de710da4b3e91cf66a826a5b31b5d59a127ab41bd0fc42863e2902ce2bbbe",
+                "sha256:e1a1c738577bca1f27e68728c910cd389b9a92152ff91d902da649c192e30c49"
             ],
-            "markers": "python_version >= '3.8'",
-            "version": "==1.14.1"
+            "markers": "python_version >= '3.9'",
+            "version": "==1.15.1"
         },
         "blinker": {
             "hashes": [
@@ -40,6 +40,104 @@
             "markers": "python_version >= '3.6'",
             "version": "==2025.1.31"
         },
+        "charset-normalizer": {
+            "hashes": [
+                "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537",
+                "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa",
+                "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a",
+                "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294",
+                "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b",
+                "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd",
+                "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601",
+                "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd",
+                "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4",
+                "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d",
+                "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2",
+                "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313",
+                "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd",
+                "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa",
+                "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8",
+                "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1",
+                "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2",
+                "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496",
+                "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d",
+                "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b",
+                "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e",
+                "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a",
+                "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4",
+                "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca",
+                "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78",
+                "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408",
+                "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5",
+                "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3",
+                "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f",
+                "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a",
+                "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765",
+                "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6",
+                "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146",
+                "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6",
+                "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9",
+                "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd",
+                "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c",
+                "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f",
+                "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545",
+                "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176",
+                "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770",
+                "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824",
+                "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f",
+                "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf",
+                "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487",
+                "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d",
+                "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd",
+                "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b",
+                "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534",
+                "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f",
+                "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b",
+                "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9",
+                "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd",
+                "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125",
+                "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9",
+                "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de",
+                "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11",
+                "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d",
+                "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35",
+                "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f",
+                "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda",
+                "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7",
+                "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a",
+                "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971",
+                "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8",
+                "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41",
+                "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d",
+                "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f",
+                "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757",
+                "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a",
+                "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886",
+                "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77",
+                "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76",
+                "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247",
+                "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85",
+                "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb",
+                "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7",
+                "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e",
+                "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6",
+                "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037",
+                "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1",
+                "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e",
+                "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807",
+                "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407",
+                "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c",
+                "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12",
+                "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3",
+                "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089",
+                "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd",
+                "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e",
+                "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00",
+                "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"
+            ],
+            "markers": "python_version >= '3.7'",
+            "version": "==3.4.1"
+        },
         "click": {
             "hashes": [
                 "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2",
@@ -74,11 +172,11 @@
         },
         "flask-cors": {
             "hashes": [
-                "sha256:5aadb4b950c4e93745034594d9f3ea6591f734bb3662e16e255ffbf5e89c88ef",
-                "sha256:b9e307d082a9261c100d8fb0ba909eec6a228ed1b60a8315fd85f783d61910bc"
+                "sha256:6ccb38d16d6b72bbc156c1c3f192bc435bfcc3c2bc864b2df1eb9b2d97b2403c",
+                "sha256:fa5cb364ead54bbf401a26dbf03030c6b18fb2fcaf70408096a572b409586b0c"
             ],
             "index": "pypi",
-            "version": "==5.0.0"
+            "version": "==5.0.1"
         },
         "flask-jwt-extended": {
             "hashes": [
@@ -199,6 +297,14 @@
             "index": "pypi",
             "version": "==23.0.0"
         },
+        "idna": {
+            "hashes": [
+                "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
+                "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
+            ],
+            "markers": "python_version >= '3.6'",
+            "version": "==3.10"
+        },
         "itsdangerous": {
             "hashes": [
                 "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
@@ -447,6 +553,14 @@
             "markers": "python_version >= '3.8'",
             "version": "==6.0.2"
         },
+        "requests": {
+            "hashes": [
+                "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
+                "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"
+            ],
+            "index": "pypi",
+            "version": "==2.32.3"
+        },
         "six": {
             "hashes": [
                 "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
diff --git a/migrations/versions/22b5bf5541c4_.py b/migrations/versions/22b5bf5541c4_.py
deleted file mode 100644
index 0e8edd6c96..0000000000
--- a/migrations/versions/22b5bf5541c4_.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""empty message
-
-Revision ID: 22b5bf5541c4
-Revises: 
-Create Date: 2025-02-19 19:55:11.728525
-
-"""
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision = '22b5bf5541c4'
-down_revision = None
-branch_labels = None
-depends_on = None
-
-
-def upgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.create_table('user',
-    sa.Column('id', sa.Integer(), nullable=False),
-    sa.Column('email', sa.String(length=120), nullable=False),
-    sa.Column('password', sa.String(length=80), nullable=False),
-    sa.Column('is_active', sa.Boolean(), nullable=False),
-    sa.PrimaryKeyConstraint('id'),
-    sa.UniqueConstraint('email')
-    )
-    # ### end Alembic commands ###
-
-
-def downgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.drop_table('user')
-    # ### end Alembic commands ###
diff --git a/migrations/versions/34a3df02bba3_.py b/migrations/versions/34a3df02bba3_.py
deleted file mode 100644
index feceaccec3..0000000000
--- a/migrations/versions/34a3df02bba3_.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""empty message
-
-Revision ID: 34a3df02bba3
-Revises: 
-Create Date: 2025-02-21 09:53:15.839016
-
-"""
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision = '34a3df02bba3'
-down_revision = None
-branch_labels = None
-depends_on = None
-
-
-def upgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.create_table('user',
-    sa.Column('id', sa.Integer(), nullable=False),
-    sa.Column('email', sa.String(length=120), nullable=False),
-    sa.Column('password', sa.String(length=80), nullable=False),
-    sa.Column('is_active', sa.Boolean(), nullable=False),
-    sa.PrimaryKeyConstraint('id'),
-    sa.UniqueConstraint('email')
-    )
-    # ### end Alembic commands ###
-
-
-def downgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.drop_table('user')
-    # ### end Alembic commands ###
diff --git a/src/api/admin.py b/src/api/admin.py
index 3eecb64140..1979841fc9 100644
--- a/src/api/admin.py
+++ b/src/api/admin.py
@@ -1,7 +1,7 @@
   
 import os
 from flask_admin import Admin
-from .models import db, User
+from .models import db, User, Genre
 from flask_admin.contrib.sqla import ModelView
 
 def setup_admin(app):
@@ -12,6 +12,7 @@ def setup_admin(app):
     
     # Add your models here, for example this is how we add a the User model to the admin
     admin.add_view(ModelView(User, db.session))
+    admin.add_view(ModelView(Genre, db.session))
 
     # You can duplicate that line to add mew models
     # admin.add_view(ModelView(YourModelName, db.session))
\ No newline at end of file
diff --git a/src/api/models.py b/src/api/models.py
index dccd8421ee..6b41856742 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -16,4 +16,18 @@ def serialize(self):
             "id": self.id,
             "email": self.email,
             # do not serialize the password, its a security breach
+        }
+    
+    # GENRES MODEL TO LOAD GENRES
+class Genre(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(250), unique=True, nullable=False)
+
+    def __repr__(self):
+        return f'<Genre {self.name}>'
+
+    def serialize(self):
+        return {
+            "id": self.id,
+            "name": self.name,
         }
\ No newline at end of file
diff --git a/src/api/routes.py b/src/api/routes.py
index 9e463890c3..23f4f61e11 100644
--- a/src/api/routes.py
+++ b/src/api/routes.py
@@ -2,11 +2,11 @@
 This module takes care of starting the API Server, Loading the DB and Adding the endpoints
 """
 from flask import Flask, request, jsonify, url_for, Blueprint
-from api.models import db, User
+from api.models import db, User, Genre
 from api.utils import generate_sitemap, APIException
 from flask_cors import CORS
 import os
-
+import requests
 # Import the Cloudinary libraries
 # ==============================
 import cloudinary
@@ -40,4 +40,24 @@ def upload_image():
     img = request.files["img"]
     img_url = cloudinary.uploader.upload(img)
     print(img_url)
-    return jsonify({"img": img_url["url"]}),200
\ No newline at end of file
+    return jsonify({"img": img_url["url"]}),200
+
+
+# ROUTE TO LOAD GENRES
+@api.route('/getGenresapi', methods=["GET"])
+def getGenresApi():
+    url = "https://api.deezer.com/genre"
+    headers = {"accept": "application/json"}
+    response = requests.get(url, headers = headers)
+    data = response.json()
+    for genre in data.get("data", []):
+        if not Genre.query.filter_by(id = genre.get("id")).first():
+            new_genre = Genre(id = genre.get("id"), name = genre.get("name"))
+            db.session.add(new_genre)
+        db.session.commit()
+    return jsonify(data)
+
+@api.route('/getGenres', methods=["GET"])
+def getGenres():
+    genres = Genre.query.filter(Genre.id != 0).all()
+    return jsonify({"genres": [genre.serialize() for genre in genres]}), 200
\ No newline at end of file
diff --git a/src/front/js/pages/genre.js b/src/front/js/pages/genre.js
index e366466cd7..6a53e12cc2 100644
--- a/src/front/js/pages/genre.js
+++ b/src/front/js/pages/genre.js
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
 import { useContext } from 'react';
 import { Context } from "../store/appContext";
 import "../../styles/genre.css"
@@ -12,12 +12,10 @@ export const Genre = () => {
     // } ----- This would be with store/actions 
 
 
-    const genre = [
-        { name: 'Rock' },
-        { name: 'Pop' },
-        { name: 'Jazz' },
+    useEffect(() => {
+        actions.loadGenres(); // Fetch genres when component mounts
+    }, []);
 
-    ]
 
     const artist = [
         { name: 'Artista 1', genre: 'Rock', image: 'https://placehold.co/50' },
@@ -35,7 +33,7 @@ export const Genre = () => {
     return (
         <div className="container">
 
-            {genre?.map((g, index) => {
+            {store.genres?.map((g, index) => {
                 return (
                     <div key={index}>
                         <h1 className="genretitle mt-3">{g.name}</h1><br />
diff --git a/src/front/js/store/flux.js b/src/front/js/store/flux.js
index cc56951a22..0f29132ab7 100755
--- a/src/front/js/store/flux.js
+++ b/src/front/js/store/flux.js
@@ -15,6 +15,8 @@ const getState = ({ getStore, getActions, setStore }) => {
 				}
 			]
 		},
+		genres: [],
+
 		actions: {
 			// Use getActions to call a function within a fuction
 			exampleFunction: () => {
@@ -22,14 +24,14 @@ const getState = ({ getStore, getActions, setStore }) => {
 			},
 
 			getMessage: async () => {
-				try{
+				try {
 					// fetching data from the backend
 					const resp = await fetch(process.env.BACKEND_URL + "/api/hello")
 					const data = await resp.json()
 					setStore({ message: data.message })
 					// don't forget to return something, that is how the async resolves
 					return data;
-				}catch(error){
+				} catch (error) {
 					console.log("Error loading message from backend", error)
 				}
 			},
@@ -46,7 +48,27 @@ const getState = ({ getStore, getActions, setStore }) => {
 
 				//reset the global store
 				setStore({ demo: demo });
-			}
+			},
+
+			// Load all genres & artists for User Home view
+			loadGenres: async () => {
+				try {
+					const options = {
+						method: 'GET', headers: {
+							"Content-Type": "application/json",
+						},
+					};
+					const response = await fetch(`${process.env.BACKEND_URL}/api/getGenres`, options)
+					if (!response.ok) {
+						console.error("Fetch error loadGenres")
+					}
+					const data = await response.json()
+					setStore({ genres: data["genres"] })
+				}
+				catch (error) {
+					console.error("Failed to get loadGenres")
+				}
+			},
 		}
 	};
 };

From 7c78c57d822974807811f0a20cbd2b2c2cc1e30f Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Wed, 5 Mar 2025 18:02:34 +0000
Subject: [PATCH 11/25] Models First commit

---
 src/api/models.py | 180 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 174 insertions(+), 6 deletions(-)

diff --git a/src/api/models.py b/src/api/models.py
index dccd8421ee..6d734f56d2 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -2,18 +2,186 @@
 
 db = SQLAlchemy()
 
-class User(db.Model):
+# class User(db.Model):
+#     id = db.Column(db.Integer, primary_key=True)
+#     email = db.Column(db.String(120), unique=True, nullable=False)
+#     password = db.Column(db.String(80), unique=False, nullable=False)
+#     is_active = db.Column(db.Boolean(), unique=False, nullable=False)
+
+
+    # ADD TO USER TABLE!!
+    # profile_photo_id = db.Column(db.Integer, db.ForeignKey('Profile_Photo.id'))
+    # profile_photo = db.relationship('Profile_Photo', backref='user', uselist=False)
+
+    # saved_artist = db.relationship('Saved_Artist', backref='user')
+    # saved_music = db.relationship('Saved_Music', backref='user')
+
+
+#     def __repr__(self):
+#         return f'<User {self.email}>'
+
+#     def serialize(self):
+#         return {
+#             "id": self.id,
+#             "email": self.email,
+#             "saved_artist": [saved.serialize() for saved in self.saved_artist],
+#             "saved_music": [saved.serialize() for saved in self.saved_music],
+                   # do not serialize the password, its a security breach
+#         }
+    
+# class Artist(db.Model):
+#     id = db.Column(db.Integer, primary_key=True)
+#     email = db.Column(db.String(120), unique=True, nullable=False)
+#     password = db.Column(db.String(80), unique=False, nullable=False)
+#     is_active = db.Column(db.Boolean(), unique=False, nullable=False)
+
+
+    # ADD TO ARTIST TABLE!!
+    # profile_photo_id = db.Column(db.Integer, db.ForeignKey('Profile_Photo.id'))
+    # profile_photo = db.relationship('Profile_Photo', backref='artist', uselist=False)
+    # artist_photos = db.relationship("Photo", backref="artist")
+    # artist_videos = db.relationship("Video", backref="artist")
+    # artist_music = db.relationship("Music", backref="artist")
+    # saved_artist = db.relationship('Saved_Artist', backref='artist')
+    
+
+#     def __repr__(self):
+#         return f'<Artist {self.email}>'
+
+#     def serialize(self):
+#         return {
+#             "id": self.id,
+#             "email": self.email,
+#             # do not serialize the password, its a security breach
+#         }
+    
+    #  PROFILE PHOTO CLASS MODEL
+class Profile_Photo(db.Model):
+    __tablename__ = "profile_photo"
+    
     id = db.Column(db.Integer, primary_key=True)
-    email = db.Column(db.String(120), unique=True, nullable=False)
-    password = db.Column(db.String(80), unique=False, nullable=False)
     is_active = db.Column(db.Boolean(), unique=False, nullable=False)
 
+    user_profile_photo = db.Column(db.String(255), nullable=True, unique=True)  # img URL or file path
+    artist_profile_photo = db.Column(db.String(255), nullable=True, unique=True)  # img URL or file path
+
+    entity_type = db.Column(db.String(50), nullable=False)  # 'user' or 'artist'
+
+    def __repr__(self):
+        return f'<ProfilePhoto {self.id, self.user_profile_photo, self.artist_profile_photo}>'
+
+    def serialize(self):
+        data = {
+        "id": self.id,
+        "is_active": self.is_active,
+        }
+        if self.user_profile_photo:
+            data["user_profile_photo"] = self.user_profile_photo
+        if self.artist_profile_photo:
+            data["artist_profile_photo"] = self.artist_profile_photo
+        return data
+
+    # ARTIST POSTS CLASS
+class Photo(db.Model):
+    __tablename__ = "photo"
+
+    id = db.Column(db.Integer, primary_key=True)
+    title = db.Column(db.String(100), nullable=False)
+    media_url = db.Column(db.Text, nullable=False, unique=True)  # Cloudinary URL
+
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+
+    def __repr__(self):
+        return f'<Photo {self.title}>'
+
+    def serialize(self):
+        return {
+            "id": self.id,
+            "title": self.title,
+            "media_url": self.media_url
+        }
+
+
+class Video(db.Model):
+    __tablename__ = "video"
+
+    id = db.Column(db.Integer, primary_key=True)
+    title = db.Column(db.String(100), nullable=False)
+    media_url = db.Column(db.Text, nullable=False, unique=True)  # Cloudinary URL
+    duration = db.Column(db.Integer, nullable=False)  # Duration in seconds
+
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+
+    def __repr__(self):
+        return f'<Video {self.title}>'
+
+    def serialize(self):
+        return {
+            "id": self.id,
+            "title": self.title,
+            "media_url": self.media_url,
+            "duration": self.duration,
+        }
+
+class Music(db.Model):
+    __tablename__ = "music"
+
+    id = db.Column(db.Integer, primary_key=True)
+    title = db.Column(db.String(200), nullable=False)
+    media_url = db.Column(db.Text, nullable=False, unique=True)  # Cloudinary URL
+    duration = db.Column(db.Integer, nullable=False)  # Duration in seconds
+
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+
+    def __repr__(self):
+        return f'<Music {self.title}>'
+
+    def serialize(self):
+        return {
+            "id": self.id,
+            "title": self.title,
+            "media_url": self.media_url,
+            "duration": self.duration,
+        }
+
+    # USER SAVED MUSIC / ARTISTS
+
+class Saved_Artist(db.Model):
+    __tablename__ = "saved_artist"
+
+    id = db.Column(db.Integer, primary_key=True)
+
+    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"))
+
+    def __repr__(self):
+        return f'<Saved_Artist {self.artist_id}>'
+
+    def serialize(self):
+        return {
+            "id": self.id,
+            "user_id": self.user_id,
+            "artist_id": self.artist_id
+        }
+
+class Saved_Music(db.Model):
+    __tablename__ = "saved_music"
+
+    id = db.Column(db.Integer, primary_key=True)
+
+    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"))
+    
+    music_id = db.Column(db.Integer, db.ForeignKey("music.id"))
+
+
     def __repr__(self):
-        return f'<User {self.email}>'
+        return f'<Saved_Music {self.music_id}>'
 
     def serialize(self):
         return {
             "id": self.id,
-            "email": self.email,
-            # do not serialize the password, its a security breach
+            "user_id": self.user_id,
+            "artist_id": self.artist_id,
+            "music_id": self.music_id
         }
\ No newline at end of file

From 2a1e870c9707a198f9ba189b98183dedb80aeee9 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Wed, 5 Mar 2025 20:00:28 +0000
Subject: [PATCH 12/25] Database models Second commit

---
 src/api/models.py | 164 ++++++++++++++++++++++++++++------------------
 1 file changed, 100 insertions(+), 64 deletions(-)

diff --git a/src/api/models.py b/src/api/models.py
index 6d734f56d2..5357b2c7db 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -2,86 +2,103 @@
 
 db = SQLAlchemy()
 
-# class User(db.Model):
-#     id = db.Column(db.Integer, primary_key=True)
-#     email = db.Column(db.String(120), unique=True, nullable=False)
-#     password = db.Column(db.String(80), unique=False, nullable=False)
-#     is_active = db.Column(db.Boolean(), unique=False, nullable=False)
-
+class User(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    email = db.Column(db.String(120), unique=True, nullable=False)
+    password = db.Column(db.String(80), unique=False, nullable=False)
+    is_active = db.Column(db.Boolean(), unique=False, nullable=False)
 
-    # ADD TO USER TABLE!!
-    # profile_photo_id = db.Column(db.Integer, db.ForeignKey('Profile_Photo.id'))
-    # profile_photo = db.relationship('Profile_Photo', backref='user', uselist=False)
+    profile_photo_id = db.Column(db.Integer, db.ForeignKey('Profile_Photo.id'))
+    profile_photo = db.relationship('Profile_Photo', backref='user', uselist=False)
 
-    # saved_artist = db.relationship('Saved_Artist', backref='user')
-    # saved_music = db.relationship('Saved_Music', backref='user')
+    saved_artist = db.relationship('Saved_Artist', backref='user')
+    saved_music = db.relationship('Saved_Music', backref='user')
 
+    followed_artists = db.relationship('Follow_Artist', backref='user')
 
-#     def __repr__(self):
-#         return f'<User {self.email}>'
+    def __repr__(self):
+        return f'<User {self.email}>'
 
-#     def serialize(self):
-#         return {
-#             "id": self.id,
-#             "email": self.email,
-#             "saved_artist": [saved.serialize() for saved in self.saved_artist],
-#             "saved_music": [saved.serialize() for saved in self.saved_music],
-                   # do not serialize the password, its a security breach
-#         }
-    
-# class Artist(db.Model):
-#     id = db.Column(db.Integer, primary_key=True)
-#     email = db.Column(db.String(120), unique=True, nullable=False)
-#     password = db.Column(db.String(80), unique=False, nullable=False)
-#     is_active = db.Column(db.Boolean(), unique=False, nullable=False)
-
-
-    # ADD TO ARTIST TABLE!!
-    # profile_photo_id = db.Column(db.Integer, db.ForeignKey('Profile_Photo.id'))
-    # profile_photo = db.relationship('Profile_Photo', backref='artist', uselist=False)
-    # artist_photos = db.relationship("Photo", backref="artist")
-    # artist_videos = db.relationship("Video", backref="artist")
-    # artist_music = db.relationship("Music", backref="artist")
-    # saved_artist = db.relationship('Saved_Artist', backref='artist')
+    def serialize(self):
+        return {
+            "id": self.id,
+            "email": self.email,
+            "saved_artist": [saved.serialize() for saved in self.saved_artist],
+            "saved_music": [saved.serialize() for saved in self.saved_music],
+        }
     
+class Artist(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    email = db.Column(db.String(120), unique=True, nullable=False)
+    password = db.Column(db.String(80), unique=False, nullable=False)
+    is_active = db.Column(db.Boolean(), unique=False, nullable=False)
+
+    profile_photo_id = db.Column(db.Integer, db.ForeignKey('Profile_Photo.id'))
+    profile_photo = db.relationship('Profile_Photo', backref='artist', uselist=False)
+
+    artist_bio = db.relationship("Photo", backref="artist")
+    artist_photos = db.relationship("Photo", backref="artist")
+    artist_videos = db.relationship("Video", backref="artist")
+    artist_music = db.relationship("Music", backref="artist")
+
+    saved_artist = db.relationship('Saved_Artist', backref='artist')
 
-#     def __repr__(self):
-#         return f'<Artist {self.email}>'
+    followers = db.relationship('Follow_Artist', backref='artist')
 
-#     def serialize(self):
-#         return {
-#             "id": self.id,
-#             "email": self.email,
-#             # do not serialize the password, its a security breach
-#         }
+    def __repr__(self):
+        return f'<Artist {self.email}>'
+
+    def serialize(self):
+        return {
+            "id": self.id,
+            "email": self.email,
+        }
     
-    #  PROFILE PHOTO CLASS MODEL
+                # USER & ARTIST PROFILE PHOTO MODEL
 class Profile_Photo(db.Model):
     __tablename__ = "profile_photo"
     
     id = db.Column(db.Integer, primary_key=True)
     is_active = db.Column(db.Boolean(), unique=False, nullable=False)
 
-    user_profile_photo = db.Column(db.String(255), nullable=True, unique=True)  # img URL or file path
-    artist_profile_photo = db.Column(db.String(255), nullable=True, unique=True)  # img URL or file path
+    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), unique=True, nullable=True)
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), unique=True, nullable=True)
 
-    entity_type = db.Column(db.String(50), nullable=False)  # 'user' or 'artist'
+    def __repr__(self):
+        return f"<ProfilePhoto id={self.id}, user_id={self.user_id}, artist_id={self.artist_id}, profile_photo={self.profile_photo}>"
+
+    def serialize(self):
+        return {
+            "id": self.id,
+            "is_active": self.is_active,
+            "profile_photo": self.profile_photo,
+            "user_id": self.user_id,
+            "artist_id": self.artist_id
+        }
+
+                # ARTIST BIO MODEL
+class Bio(db.Model):
+    __tablename__ = "bio"
+
+    id = db.Column(db.Integer, primary_key=True)
+
+    text = db.Column(db.String(1000), nullable=True)
+
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
 
     def __repr__(self):
-        return f'<ProfilePhoto {self.id, self.user_profile_photo, self.artist_profile_photo}>'
+        shortened_text = self.text[:50] + '...' if self.text else "No bio available"
+        return f'<Bio text={shortened_text}>'
 
     def serialize(self):
-        data = {
-        "id": self.id,
-        "is_active": self.is_active,
+        return {
+            "id": self.id,
+            "text": self.text,
+            "artist_id": self.artist_id
         }
-        if self.user_profile_photo:
-            data["user_profile_photo"] = self.user_profile_photo
-        if self.artist_profile_photo:
-            data["artist_profile_photo"] = self.artist_profile_photo
-        return data
 
-    # ARTIST POSTS CLASS
+
+                # ARTIST PHOTO MODEL
 class Photo(db.Model):
     __tablename__ = "photo"
 
@@ -101,14 +118,14 @@ def serialize(self):
             "media_url": self.media_url
         }
 
-
+                # ARTIST VIDEO MODEL
 class Video(db.Model):
     __tablename__ = "video"
 
     id = db.Column(db.Integer, primary_key=True)
     title = db.Column(db.String(100), nullable=False)
     media_url = db.Column(db.Text, nullable=False, unique=True)  # Cloudinary URL
-    duration = db.Column(db.Integer, nullable=False)  # Duration in seconds
+    duration = db.Column(db.Integer, nullable=False)
 
     artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
 
@@ -123,13 +140,14 @@ def serialize(self):
             "duration": self.duration,
         }
 
+                # ARTIST MUSIC MODEL
 class Music(db.Model):
     __tablename__ = "music"
 
     id = db.Column(db.Integer, primary_key=True)
     title = db.Column(db.String(200), nullable=False)
     media_url = db.Column(db.Text, nullable=False, unique=True)  # Cloudinary URL
-    duration = db.Column(db.Integer, nullable=False)  # Duration in seconds
+    duration = db.Column(db.Integer, nullable=False)
 
     artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
 
@@ -144,8 +162,8 @@ def serialize(self):
             "duration": self.duration,
         }
 
-    # USER SAVED MUSIC / ARTISTS
 
+                # USER SAVED MUSIC & SAVED ARTISTS MODEL
 class Saved_Artist(db.Model):
     __tablename__ = "saved_artist"
 
@@ -171,10 +189,8 @@ class Saved_Music(db.Model):
 
     user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
     artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"))
-    
     music_id = db.Column(db.Integer, db.ForeignKey("music.id"))
 
-
     def __repr__(self):
         return f'<Saved_Music {self.music_id}>'
 
@@ -184,4 +200,24 @@ def serialize(self):
             "user_id": self.user_id,
             "artist_id": self.artist_id,
             "music_id": self.music_id
+        }
+    
+
+                # FOLLOW ARTIST MODEL
+class Follow_Artist(db.Model):
+    __tablename__ = "follow_artist"
+
+    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), primary_key=True)
+
+    is_active = db.Column(db.Boolean, default=True)
+
+    def __repr__(self):
+        return f'<Follow_Artist user_id={self.user_id}, artist_id={self.artist_id}, is_active={self.is_active}>'
+
+    def serialize(self):
+        return {
+            "user_id": self.user_id,
+            "artist_id": self.artist_id,
+            "is_active": self.is_active
         }
\ No newline at end of file

From a8cfc5a84fad9388ea3e3c53fd179d926507f405 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Wed, 5 Mar 2025 20:07:34 +0000
Subject: [PATCH 13/25] Database models done

---
 src/api/models.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/api/models.py b/src/api/models.py
index 5357b2c7db..6d858a9640 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -23,6 +23,7 @@ def serialize(self):
         return {
             "id": self.id,
             "email": self.email,
+            # do not serialize the password, its a security breach
             "saved_artist": [saved.serialize() for saved in self.saved_artist],
             "saved_music": [saved.serialize() for saved in self.saved_music],
         }
@@ -52,6 +53,7 @@ def serialize(self):
         return {
             "id": self.id,
             "email": self.email,
+            # do not serialize the password, its a security breach
         }
     
                 # USER & ARTIST PROFILE PHOTO MODEL

From a69c23d1ba5a620ae3aaef3b002038ec22224601 Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Wed, 5 Mar 2025 20:22:20 +0000
Subject: [PATCH 14/25] creacion de usuarios y login

---
 Pipfile                              |   4 +-
 Pipfile.lock                         |  38 +--
 migrations/versions/22b5bf5541c4_.py |  35 ---
 migrations/versions/34a3df02bba3_.py |  35 ---
 src/api/auth.py                      |  13 +
 src/api/models.py                    |  27 +-
 src/api/routes.py                    |  52 +++-
 src/app.py                           |   3 +
 src/front/js/pages/login.js          | 373 +++++++++++++++++----------
 9 files changed, 359 insertions(+), 221 deletions(-)
 delete mode 100644 migrations/versions/22b5bf5541c4_.py
 delete mode 100644 migrations/versions/34a3df02bba3_.py
 create mode 100644 src/api/auth.py

diff --git a/Pipfile b/Pipfile
index b461e2e4ee..bc3a6478e3 100644
--- a/Pipfile
+++ b/Pipfile
@@ -18,8 +18,10 @@ gunicorn = "*"
 cloudinary = "*"
 flask-admin = "*"
 typing-extensions = "*"
-flask-jwt-extended = "==4.6.0"
 wtforms = "==3.1.2"
+flask-extended = "*"
+flask-jwt-extended = "*"
+pyjwt = "==2.9.0"
 
 [requires]
 python_version = "3.10"
diff --git a/Pipfile.lock b/Pipfile.lock
index 508225b0a1..2b5d1e0627 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "4f0e9a772f04b621ff0313b7ecfa468af1526aa27df8bfcacac6955d499d352d"
+            "sha256": "df7144212363e2fb107242f0448476de13fa283a57b574ff560e2a499fbc4049"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -18,11 +18,11 @@
     "default": {
         "alembic": {
             "hashes": [
-                "sha256:1acdd7a3a478e208b0503cd73614d5e4c6efafa4e73518bb60e4f2846a37b1c5",
-                "sha256:496e888245a53adf1498fcab31713a469c65836f8de76e01399aa1c3e90dd213"
+                "sha256:197de710da4b3e91cf66a826a5b31b5d59a127ab41bd0fc42863e2902ce2bbbe",
+                "sha256:e1a1c738577bca1f27e68728c910cd389b9a92152ff91d902da649c192e30c49"
             ],
-            "markers": "python_version >= '3.8'",
-            "version": "==1.14.1"
+            "markers": "python_version >= '3.9'",
+            "version": "==1.15.1"
         },
         "blinker": {
             "hashes": [
@@ -74,19 +74,27 @@
         },
         "flask-cors": {
             "hashes": [
-                "sha256:5aadb4b950c4e93745034594d9f3ea6591f734bb3662e16e255ffbf5e89c88ef",
-                "sha256:b9e307d082a9261c100d8fb0ba909eec6a228ed1b60a8315fd85f783d61910bc"
+                "sha256:6ccb38d16d6b72bbc156c1c3f192bc435bfcc3c2bc864b2df1eb9b2d97b2403c",
+                "sha256:fa5cb364ead54bbf401a26dbf03030c6b18fb2fcaf70408096a572b409586b0c"
+            ],
+            "index": "pypi",
+            "version": "==5.0.1"
+        },
+        "flask-extended": {
+            "hashes": [
+                "sha256:7d4951573da1fb680185970bfb6427934809ddd4a7d372acf67736d4455ae7be",
+                "sha256:dcf785327209e1967b01e62868f3ff6bc1401a2359746972111969dc16a7fd29"
             ],
             "index": "pypi",
-            "version": "==5.0.0"
+            "version": "==0.2"
         },
         "flask-jwt-extended": {
             "hashes": [
-                "sha256:63a28fc9731bcc6c4b8815b6f954b5904caa534fc2ae9b93b1d3ef12930dca95",
-                "sha256:9215d05a9413d3855764bcd67035e75819d23af2fafb6b55197eb5a3313fdfb2"
+                "sha256:52f35bf0985354d7fb7b876e2eb0e0b141aaff865a22ff6cc33d9a18aa987978",
+                "sha256:8085d6757505b6f3291a2638c84d207e8f0ad0de662d1f46aa2f77e658a0c976"
             ],
             "index": "pypi",
-            "version": "==4.6.0"
+            "version": "==4.7.1"
         },
         "flask-migrate": {
             "hashes": [
@@ -374,11 +382,11 @@
         },
         "pyjwt": {
             "hashes": [
-                "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953",
-                "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"
+                "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850",
+                "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"
             ],
-            "markers": "python_version >= '3.9'",
-            "version": "==2.10.1"
+            "index": "pypi",
+            "version": "==2.9.0"
         },
         "python-dotenv": {
             "hashes": [
diff --git a/migrations/versions/22b5bf5541c4_.py b/migrations/versions/22b5bf5541c4_.py
deleted file mode 100644
index 0e8edd6c96..0000000000
--- a/migrations/versions/22b5bf5541c4_.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""empty message
-
-Revision ID: 22b5bf5541c4
-Revises: 
-Create Date: 2025-02-19 19:55:11.728525
-
-"""
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision = '22b5bf5541c4'
-down_revision = None
-branch_labels = None
-depends_on = None
-
-
-def upgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.create_table('user',
-    sa.Column('id', sa.Integer(), nullable=False),
-    sa.Column('email', sa.String(length=120), nullable=False),
-    sa.Column('password', sa.String(length=80), nullable=False),
-    sa.Column('is_active', sa.Boolean(), nullable=False),
-    sa.PrimaryKeyConstraint('id'),
-    sa.UniqueConstraint('email')
-    )
-    # ### end Alembic commands ###
-
-
-def downgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.drop_table('user')
-    # ### end Alembic commands ###
diff --git a/migrations/versions/34a3df02bba3_.py b/migrations/versions/34a3df02bba3_.py
deleted file mode 100644
index feceaccec3..0000000000
--- a/migrations/versions/34a3df02bba3_.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""empty message
-
-Revision ID: 34a3df02bba3
-Revises: 
-Create Date: 2025-02-21 09:53:15.839016
-
-"""
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision = '34a3df02bba3'
-down_revision = None
-branch_labels = None
-depends_on = None
-
-
-def upgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.create_table('user',
-    sa.Column('id', sa.Integer(), nullable=False),
-    sa.Column('email', sa.String(length=120), nullable=False),
-    sa.Column('password', sa.String(length=80), nullable=False),
-    sa.Column('is_active', sa.Boolean(), nullable=False),
-    sa.PrimaryKeyConstraint('id'),
-    sa.UniqueConstraint('email')
-    )
-    # ### end Alembic commands ###
-
-
-def downgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.drop_table('user')
-    # ### end Alembic commands ###
diff --git a/src/api/auth.py b/src/api/auth.py
new file mode 100644
index 0000000000..e33936016b
--- /dev/null
+++ b/src/api/auth.py
@@ -0,0 +1,13 @@
+from flask_jwt_extended import JWTManager
+from api.models import User
+
+jwt = JWTManager()
+
+@jwt.user_identity_loader
+def user_identity_lookup(user):
+    return user.id
+
+@jwt.user_lookup_loader
+def user_lookuo_callback(_jwtheader, jwt_data):
+    identity = jwt_data["sub"]
+    return User.query.filter_by(id=identity).one_or_none()
\ No newline at end of file
diff --git a/src/api/models.py b/src/api/models.py
index dccd8421ee..6e5e2956d1 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -1,19 +1,40 @@
 from flask_sqlalchemy import SQLAlchemy
+from werkzeug.security import generate_password_hash, check_password_hash
 
 db = SQLAlchemy()
 
 class User(db.Model):
     id = db.Column(db.Integer, primary_key=True)
+    fullName = db.Column(db.String(120), unique=True, nullable=False)
+    username = db.Column(db.String(120), unique=True, nullable=False)
+    address = db.Column(db.String(120), unique=True, nullable=False)
     email = db.Column(db.String(120), unique=True, nullable=False)
-    password = db.Column(db.String(80), unique=False, nullable=False)
-    is_active = db.Column(db.Boolean(), unique=False, nullable=False)
+    password_hash = db.Column(db.String(512), unique=False, nullable=False)
+    is_artist = db.Column(db.Boolean(), default=False)
+    is_active = db.Column(db.Boolean(), default=True)
 
     def __repr__(self):
         return f'<User {self.email}>'
+    
+    def artist(is_artist):
+        if is_artist:
+            return "Si"
+        else:
+            return "No"
 
     def serialize(self):
         return {
             "id": self.id,
+            "fullName": self.fullName,
+            "username": self.username,
             "email": self.email,
+            "address":self.address,
+            "artist":self.artist()
             # do not serialize the password, its a security breach
-        }
\ No newline at end of file
+        }
+    
+    def set_password(self, password):
+        self.password_hash = generate_password_hash(password)
+
+    def check_password(self,password):
+        return check_password_hash(self.password_hash,password)
\ No newline at end of file
diff --git a/src/api/routes.py b/src/api/routes.py
index 9e463890c3..b1c028e7cb 100644
--- a/src/api/routes.py
+++ b/src/api/routes.py
@@ -7,6 +7,8 @@
 from flask_cors import CORS
 import os
 
+from flask_jwt_extended import create_access_token, current_user, jwt_required
+
 # Import the Cloudinary libraries
 # ==============================
 import cloudinary
@@ -40,4 +42,52 @@ def upload_image():
     img = request.files["img"]
     img_url = cloudinary.uploader.upload(img)
     print(img_url)
-    return jsonify({"img": img_url["url"]}),200
\ No newline at end of file
+    return jsonify({"img": img_url["url"]}),200
+
+
+# Creacion de usuario 
+@api.route('/register', methods=['POST'])
+def register():
+    fullName = request.json.get('fullName', None)
+    username = request.json.get('username', None)
+    address = request.json.get('address', None)
+    email = request.json.get('email', None)
+    password = request.json.get('password', None)
+
+    if not fullName or not username or not email or not password:
+        return jsonify({"msg": "Missing required fields"}), 400
+
+    existing_user = User.query.filter_by(email=email).first()
+    if existing_user:
+        return jsonify({"msg": "Email already exists"}), 400
+
+    existing_user = User.query.filter_by(username=username).first()
+    if existing_user:
+        return jsonify({"msg": "Username already exists"}), 400
+
+    user = User(fullName=fullName, username=username, address=address, email=email, is_artist=True, is_active=True)
+    user.set_password(password)
+
+    db.session.add(user)
+    db.session.commit()
+
+    return jsonify({"msg": "User has been created"}), 201
+
+@api.route('/login', methods=['POST'])
+def generate_token():
+    username = request.json.get("username", None)
+    password = request.json.get("password", None)
+
+    user = User.query.filter_by(username=username).one_or_none()
+
+    if not user or not user.check_password(password):
+        return jsonify("Wrong username or password"), 401
+    
+    access_token = create_access_token(identity=user)  # Se pasa user.id
+    return jsonify(access_token=access_token)
+
+
+@api.route('/profile', methods=['GET'])
+@jwt_required()
+def get_current_user():
+    return jsonify(current_user.serialize()), 200
diff --git a/src/app.py b/src/app.py
index 0ea8351d5f..2ad028d6a2 100644
--- a/src/app.py
+++ b/src/app.py
@@ -10,6 +10,7 @@
 from api.routes import api
 from api.admin import setup_admin
 from api.commands import setup_commands
+from api.auth import jwt
 
 # from models import Person
 
@@ -42,6 +43,8 @@
 
 # Handle/serialize errors like a JSON object
 
+#inicializo el jwt con mi app
+jwt.init_app(app)
 
 @app.errorhandler(APIException)
 def handle_invalid_usage(error):
diff --git a/src/front/js/pages/login.js b/src/front/js/pages/login.js
index 5c52ced40f..043755db23 100644
--- a/src/front/js/pages/login.js
+++ b/src/front/js/pages/login.js
@@ -8,6 +8,92 @@ export const Login = () => {
   const [showRegister, setShowRegister] = useState(false);
   const [showForgoten, setShowForgoten] = useState(false);
 
+  //Estado para almacenar datos del formulario de registro
+
+  const[formulario, setFormulario] = useState({
+    fullName:"",
+    username:"",
+    email:"",
+    address:"",
+    password:"",
+    confirmPassword:"",
+  });
+
+  // Estados para manejar el login
+  const [loginData, setLoginData] = useState({
+    username:"",
+    password:"",
+  });
+
+  // Manejar los cambios en los inputs del registro
+  const handleChange = (e) => {
+    setFormulario({...formulario, [e.target.name]: e.target.value});
+  };
+
+  // Manejar cambios en  los inpusts del login
+  const handleLoginChange = (e) => {
+    console.log("cambir campos: ", e.target.name, "Nuevo valor:", e.target.value);
+    setLoginData({...loginData, [e.target.name]:e.target.value});
+  };
+
+  // Enviar formulario de registro
+  const handleRegister = async (e) =>{
+    e.preventDefault();
+    
+    if (formulario.password !== formulario.confirmPassword){
+      alert("Las contraseñas no coinciden");
+      return;
+    }
+    
+    console.log("Datos del formulario de registro:", formulario); // Verifica que los datos sean correctos antes de enviarlos
+
+    try{
+      const response = await fetch("https://fluffy-chainsaw-v6qq999gg9xwfx99v-3001.app.github.dev/api/register",{
+        method:"POST",
+        headers:{"Content-type":"application/json"},
+        body:JSON.stringify(formulario),
+      });
+
+      const data = await response.json();
+
+      if(response.ok){
+        alert("Usuario registrado con exito");
+        setShowRegister(false);
+        setShowLogin(true);
+      }else{
+        alert(data.message || "Error al registrar usuario")
+      }
+    } catch(error){
+      alert("Error en el servidor")
+    }
+  };
+
+  // Enviar formulario de inicio de sesion
+  const handleLogin = async (e) =>{
+    e.preventDefault();
+
+    try{
+      const response = await fetch("https://fluffy-chainsaw-v6qq999gg9xwfx99v-3001.app.github.dev/login", {
+        method:"POST",
+        headers:{"Content-Type":"application/json"},
+        body: JSON.stringify(loginData)
+      });
+
+      const data = await response.json();
+
+      if(response.ok){
+        alert("Inicio de sesion correcto");
+        localStorage.setItem("Token", data.token); // Guarda el token en local
+        localStorage.setItem("user", JSON.stringify(data.user)) // guarda los datos del usuario
+        // aqui puedes redirir a otra pagina
+      } else{
+        alert(data.message || "Error al iniciar sesion")
+      }
+    }catch (error){
+      alert("Error en el servidor")
+    }
+  }
+
   return (
     <div
       style={{
@@ -52,146 +138,171 @@ export const Login = () => {
 
         {/* Formulario de inicio de sesión */}
         {showLogin && !showForgoten && (
-          <form>
-            <h2 className="text-center mb-4">Iniciar sesión</h2>
-            <div className="mb-3">
-              <input
-                type="text"
-                className="form-control form-control-lg"
-                placeholder="Nombre de usuario"
-                required
-              />
-            </div>
-            <div className="mb-3">
-              <input
-                type="password"
-                className="form-control form-control-lg"
-                placeholder="Contraseña"
-                required
-              />
-            </div>
-            <button type="submit" className="btn btn-danger w-100 py-2">
-              Ingresar
-            </button>
-            <div className="text-center mt-2">
-              <a href="#" className="text-decoration-none" onClick={() =>
-                setShowForgoten(true)
-              }>¿He olvidado mi contraseña?</a>
-              <button
-                type="button"
-                className="btn btn-link w-100 mt-2"
-                onClick={() => {
-                  setShowForgoten(false);
-                  setShowLogin(false);
-                  setShowRegister(false)
-                }}
-              >
-                Volver
-              </button>
-            </div>
-          </form>
-        )}
-
-        {/* Formulario de registro */}
-        {showRegister && (
-          <form>
-            <h2 className="text-center mb-4">Registro</h2>
-            <div className="mb-3">
-              <input
-                type="text"
-                className="form-control form-control-lg"
-                placeholder="Nombre y apellidos"
-                required
-              />
-            </div>
-            <div className="mb-3">
-              <input
-                type="text"
-                className="form-control form-control-lg"
-                placeholder="Nombre de usuario"
-                required
-              />
-            </div>
-            <div className="mb-3">
-              <input
-                type="email"
-                className="form-control form-control-lg"
-                placeholder="Correo electrónico"
-                required
-              />
-            </div>
-            <div className="mb-3">
-              <input
-                type="text"
-                className="form-control form-control-lg"
-                placeholder="Dirección"
-                required
-              />
-            </div>
-            <div className="mb-3">
-              <input
-                type="password"
-                className="form-control form-control-lg"
-                placeholder="Contraseña"
-                required
-              />
-            </div>
-            <div className="mb-3">
-              <input
-                type="password"
-                className="form-control form-control-lg"
-                placeholder="Confirmar contraseña"
-                required
-              />
-            </div>
-            <div className="mb-3">
-              <label className="form-label">Subir foto de perfil</label>
-              <input type="file" className="form-control form-control-lg" />
-            </div>
-            <button type="submit" className="btn btn-success w-100 py-2">
-              Registrarse
-            </button>
+          <form onSubmit={handleLogin}>
+          <h2 className="text-center mb-4">Iniciar sesión</h2>
+          <div className="mb-3">
+            <input
+              type="text"
+              className="form-control form-control-lg"
+              placeholder="Nombre de usuario"
+              name = "username"
+              value={loginData.username}
+              onChange={handleLoginChange}
+              required
+            />
+          </div>
+          <div className="mb-3">
+            <input
+              type="password"
+              className="form-control form-control-lg"
+              placeholder="Contraseña"
+              name = "password"
+              value={loginData.password}
+              onChange={handleLoginChange}
+              required
+            />
+          </div>
+          <button type="submit" className="btn btn-danger w-100 py-2">
+            Ingresar
+          </button>
+          <div className="text-center mt-2">
+            <a href="#" className="text-decoration-none" onClick={() =>
+              setShowForgoten(true)
+            }>¿He olvidado mi contraseña?</a>
             <button
               type="button"
               className="btn btn-link w-100 mt-2"
-              onClick={() => setShowRegister(false)}
+              onClick={() => {
+                setShowForgoten(false);
+                setShowLogin(false);
+                setShowRegister(false)
+              }}
             >
               Volver
             </button>
-          </form>
+          </div>
+        </form >
+        )}
+
+        {/* Formulario de registro */}
+        {showRegister && (
+          <form onSubmit={handleRegister}>
+          <h2 className="text-center mb-4">Registro</h2>
+          <div className="mb-3">
+            <input
+              type="text"
+              className="form-control form-control-lg"
+              placeholder="Nombre y apellidos"
+              name="fullName"
+              value={formulario.fullName}
+              onChange={handleChange}
+              required
+            />
+          </div>
+          <div className="mb-3">
+            <input
+              type="text"
+              className="form-control form-control-lg"
+              placeholder="Nombre de usuario"
+              name="username"
+              value={formulario.username}
+              onChange={handleChange}
+              required
+            />
+          </div>
+          <div className="mb-3">
+            <input
+              type="email"
+              className="form-control form-control-lg"
+              placeholder="Correo electrónico"
+              name = "email"
+              value={formulario.email}
+              onChange={handleChange}
+              required
+            />
+          </div>
+          <div className="mb-3">
+            <input
+              type="text"
+              className="form-control form-control-lg"
+              placeholder="Dirección"
+              name = "address"
+              value={formulario.address}
+              onChange={handleChange}
+              required
+            />
+          </div>
+          <div className="mb-3">
+            <input
+              type="password"
+              className="form-control form-control-lg"
+              placeholder="Contraseña"
+              name = "password"
+              value={formulario.password}
+              onChange={handleChange}
+              required
+            />
+          </div>
+          <div className="mb-3">
+            <input
+              type="password"
+              className="form-control form-control-lg"
+              placeholder="Confirmar contraseña"
+              name = "confirmPassword"
+              value={formulario.confirmPassword}
+              onChange={handleChange}
+              required
+            />
+          </div>
+          <div className="mb-3">
+            <label className="form-label">Subir foto de perfil</label>
+            <input type="file" className="form-control form-control-lg" />
+          </div>
+          <button type="submit" className="btn btn-success w-100 py-2">
+            Registrarse
+          </button>
+          <button
+            type="button"
+            className="btn btn-link w-100 mt-2"
+            onClick={() => setShowRegister(false)}
+          >
+            Volver
+          </button>
+        </form>
         )}
         {/* Formulario de recuperar contraseña*/}
         {showForgoten && (
-          <form>
-            <h2 className="text-center mb-4">¿He olvidado mi contraseña?</h2>
-            <div className="mb-3">
-              <input
-                type="text"
-                className="form-control form-control-lg"
-                placeholder="Nomber de usuario"
-                required
-              />
-            </div>
-            <div className="mb-3">
-              <input
-                type="password"
-                className="form-control form-control-lg"
-                placeholder="Nueva contraseña"
-                required
-              />
-            </div>
-            <button
-              type="button"
-              className="btn btn-link w-100 mt-2"
-              onClick={() => {
-                setShowLogin(true);
-                setShowRegister(false);
-                setShowForgoten(false)
-              }}
-            >
-              Volver
-            </button>
-          </form>)}
+          <form onSubmit={handleRegister}>
+          <h2 className="text-center mb-4">¿He olvidado mi contraseña?</h2>
+          <div className="mb-3">
+            <input
+              type="text"
+              className="form-control form-control-lg"
+              placeholder="Nomber de usuario"
+              required
+            />
+          </div>
+          <div className="mb-3">
+            <input
+              type="password"
+              className="form-control form-control-lg"
+              placeholder="Nueva contraseña"
+              required
+            />
+          </div>
+          <button
+            type="button"
+            className="btn btn-link w-100 mt-2"
+            onClick={() => {
+              setShowLogin(true);
+              setShowRegister(false);
+              setShowForgoten(false)
+            }}
+          >
+            Volver
+          </button>
+        </form>
+      )}
 
 
       </div>

From 9db4a6f8b92a609ed38ffec9a9f6ff922d287830 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Wed, 5 Mar 2025 21:08:07 +0000
Subject: [PATCH 15/25] Database Models BACKEND done after reset migrations

---
 migrations/versions/22b5bf5541c4_.py | 35 ----------------------------
 migrations/versions/34a3df02bba3_.py | 35 ----------------------------
 src/api/models.py                    | 23 +++++++++---------
 3 files changed, 11 insertions(+), 82 deletions(-)
 delete mode 100644 migrations/versions/22b5bf5541c4_.py
 delete mode 100644 migrations/versions/34a3df02bba3_.py

diff --git a/migrations/versions/22b5bf5541c4_.py b/migrations/versions/22b5bf5541c4_.py
deleted file mode 100644
index 0e8edd6c96..0000000000
--- a/migrations/versions/22b5bf5541c4_.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""empty message
-
-Revision ID: 22b5bf5541c4
-Revises: 
-Create Date: 2025-02-19 19:55:11.728525
-
-"""
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision = '22b5bf5541c4'
-down_revision = None
-branch_labels = None
-depends_on = None
-
-
-def upgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.create_table('user',
-    sa.Column('id', sa.Integer(), nullable=False),
-    sa.Column('email', sa.String(length=120), nullable=False),
-    sa.Column('password', sa.String(length=80), nullable=False),
-    sa.Column('is_active', sa.Boolean(), nullable=False),
-    sa.PrimaryKeyConstraint('id'),
-    sa.UniqueConstraint('email')
-    )
-    # ### end Alembic commands ###
-
-
-def downgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.drop_table('user')
-    # ### end Alembic commands ###
diff --git a/migrations/versions/34a3df02bba3_.py b/migrations/versions/34a3df02bba3_.py
deleted file mode 100644
index feceaccec3..0000000000
--- a/migrations/versions/34a3df02bba3_.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""empty message
-
-Revision ID: 34a3df02bba3
-Revises: 
-Create Date: 2025-02-21 09:53:15.839016
-
-"""
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision = '34a3df02bba3'
-down_revision = None
-branch_labels = None
-depends_on = None
-
-
-def upgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.create_table('user',
-    sa.Column('id', sa.Integer(), nullable=False),
-    sa.Column('email', sa.String(length=120), nullable=False),
-    sa.Column('password', sa.String(length=80), nullable=False),
-    sa.Column('is_active', sa.Boolean(), nullable=False),
-    sa.PrimaryKeyConstraint('id'),
-    sa.UniqueConstraint('email')
-    )
-    # ### end Alembic commands ###
-
-
-def downgrade():
-    # ### commands auto generated by Alembic - please adjust! ###
-    op.drop_table('user')
-    # ### end Alembic commands ###
diff --git a/src/api/models.py b/src/api/models.py
index 6d858a9640..944f222225 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -3,13 +3,14 @@
 db = SQLAlchemy()
 
 class User(db.Model):
+
     id = db.Column(db.Integer, primary_key=True)
     email = db.Column(db.String(120), unique=True, nullable=False)
     password = db.Column(db.String(80), unique=False, nullable=False)
     is_active = db.Column(db.Boolean(), unique=False, nullable=False)
 
-    profile_photo_id = db.Column(db.Integer, db.ForeignKey('Profile_Photo.id'))
-    profile_photo = db.relationship('Profile_Photo', backref='user', uselist=False)
+    profile_photo_id = db.Column(db.Integer, db.ForeignKey('profile_photo.id'), unique=True)
+    profile_photo = db.relationship('Profile_Photo', uselist=False, foreign_keys=[profile_photo_id])
 
     saved_artist = db.relationship('Saved_Artist', backref='user')
     saved_music = db.relationship('Saved_Music', backref='user')
@@ -29,15 +30,16 @@ def serialize(self):
         }
     
 class Artist(db.Model):
+
     id = db.Column(db.Integer, primary_key=True)
     email = db.Column(db.String(120), unique=True, nullable=False)
     password = db.Column(db.String(80), unique=False, nullable=False)
     is_active = db.Column(db.Boolean(), unique=False, nullable=False)
 
-    profile_photo_id = db.Column(db.Integer, db.ForeignKey('Profile_Photo.id'))
-    profile_photo = db.relationship('Profile_Photo', backref='artist', uselist=False)
+    profile_photo_id = db.Column(db.Integer, db.ForeignKey('profile_photo.id'), unique=True)
+    profile_photo = db.relationship('Profile_Photo', uselist=False, foreign_keys=[profile_photo_id])
 
-    artist_bio = db.relationship("Photo", backref="artist")
+    artist_bio = db.relationship("Bio", backref="artist")
     artist_photos = db.relationship("Photo", backref="artist")
     artist_videos = db.relationship("Video", backref="artist")
     artist_music = db.relationship("Music", backref="artist")
@@ -61,21 +63,18 @@ class Profile_Photo(db.Model):
     __tablename__ = "profile_photo"
     
     id = db.Column(db.Integer, primary_key=True)
-    is_active = db.Column(db.Boolean(), unique=False, nullable=False)
 
-    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), unique=True, nullable=True)
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), unique=True, nullable=True)
+    media_url = db.Column(db.String(255), nullable=False)
+    is_active = db.Column(db.Boolean(), unique=False, nullable=False)
 
     def __repr__(self):
-        return f"<ProfilePhoto id={self.id}, user_id={self.user_id}, artist_id={self.artist_id}, profile_photo={self.profile_photo}>"
+        return f"<Profile_Photo {self.id}>"
 
     def serialize(self):
         return {
             "id": self.id,
+            "media_url": self.media_url,
             "is_active": self.is_active,
-            "profile_photo": self.profile_photo,
-            "user_id": self.user_id,
-            "artist_id": self.artist_id
         }
 
                 # ARTIST BIO MODEL

From 73653fc312130e89a65efc17d62138d4dcfb61a3 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Thu, 6 Mar 2025 10:26:15 +0000
Subject: [PATCH 16/25] Database models Final commit

---
 src/api/models.py | 130 +++++++++++++---------------------------------
 1 file changed, 37 insertions(+), 93 deletions(-)

diff --git a/src/api/models.py b/src/api/models.py
index 944f222225..bffd963213 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -2,111 +2,74 @@
 
 db = SQLAlchemy()
 
+        #  USER REGISTER AND PROFILE MODEL
 class User(db.Model):
+    __tablename__ = "user"
 
     id = db.Column(db.Integer, primary_key=True)
+
+    full_name = db.Column(db.String(120), unique=True, nullable=True)
+    username = db.Column(db.String(120), unique=True, nullable=True)
+
     email = db.Column(db.String(120), unique=True, nullable=False)
     password = db.Column(db.String(80), unique=False, nullable=False)
-    is_active = db.Column(db.Boolean(), unique=False, nullable=False)
 
-    profile_photo_id = db.Column(db.Integer, db.ForeignKey('profile_photo.id'), unique=True)
-    profile_photo = db.relationship('Profile_Photo', uselist=False, foreign_keys=[profile_photo_id])
+    is_artist = db.Column(db.Boolean, default=False) # Check if account is artist
+    profile_photo = db.Column(db.String(255), nullable=True)  # Profile photo URL
 
-    saved_artist = db.relationship('Saved_Artist', backref='user')
+    #  Relationships
+    followed_artists = db.relationship('Follow_Artist', backref='follow_artist')
     saved_music = db.relationship('Saved_Music', backref='user')
 
-    followed_artists = db.relationship('Follow_Artist', backref='user')
-
     def __repr__(self):
-        return f'<User {self.email}>'
+        return f'<User {self.username}>'
 
     def serialize(self):
         return {
             "id": self.id,
+            "full_name": self.full_name,
+            "username": self.username,
             "email": self.email,
-            # do not serialize the password, its a security breach
-            "saved_artist": [saved.serialize() for saved in self.saved_artist],
-            "saved_music": [saved.serialize() for saved in self.saved_music],
+            "is_artist": self.is_artist,
+            "profile_photo": self.profile_photo,
         }
-    
-class Artist(db.Model):
+
+        # ARTIST PROFILE MODEL
+class Artist_Profile(db.Model):
+    __tablename__ = "artist_profile"
 
     id = db.Column(db.Integer, primary_key=True)
-    email = db.Column(db.String(120), unique=True, nullable=False)
-    password = db.Column(db.String(80), unique=False, nullable=False)
-    is_active = db.Column(db.Boolean(), unique=False, nullable=False)
+    bio = db.Column(db.Text, nullable=True)
 
-    profile_photo_id = db.Column(db.Integer, db.ForeignKey('profile_photo.id'), unique=True)
-    profile_photo = db.relationship('Profile_Photo', uselist=False, foreign_keys=[profile_photo_id])
+    # Relationships
+    artist_id = db.Column(db.Integer, db.ForeignKey('users.id'), unique=True, nullable=False)
 
-    artist_bio = db.relationship("Bio", backref="artist")
     artist_photos = db.relationship("Photo", backref="artist")
     artist_videos = db.relationship("Video", backref="artist")
     artist_music = db.relationship("Music", backref="artist")
 
-    saved_artist = db.relationship('Saved_Artist', backref='artist')
-
-    followers = db.relationship('Follow_Artist', backref='artist')
-
     def __repr__(self):
-        return f'<Artist {self.email}>'
+        return f'<Artist_Profile {self.id}>'
 
     def serialize(self):
         return {
             "id": self.id,
-            "email": self.email,
-            # do not serialize the password, its a security breach
+            "artist_id": self.artist_id,
+            "bio": self.bio,
+            "artist_photos": self.artist_photos,
+            "artist_videos": self.artist_videos,
+            "artist_music": self.artist_music
         }
     
-                # USER & ARTIST PROFILE PHOTO MODEL
-class Profile_Photo(db.Model):
-    __tablename__ = "profile_photo"
-    
-    id = db.Column(db.Integer, primary_key=True)
-
-    media_url = db.Column(db.String(255), nullable=False)
-    is_active = db.Column(db.Boolean(), unique=False, nullable=False)
-
-    def __repr__(self):
-        return f"<Profile_Photo {self.id}>"
-
-    def serialize(self):
-        return {
-            "id": self.id,
-            "media_url": self.media_url,
-            "is_active": self.is_active,
-        }
-
-                # ARTIST BIO MODEL
-class Bio(db.Model):
-    __tablename__ = "bio"
-
-    id = db.Column(db.Integer, primary_key=True)
-
-    text = db.Column(db.String(1000), nullable=True)
-
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
-
-    def __repr__(self):
-        shortened_text = self.text[:50] + '...' if self.text else "No bio available"
-        return f'<Bio text={shortened_text}>'
-
-    def serialize(self):
-        return {
-            "id": self.id,
-            "text": self.text,
-            "artist_id": self.artist_id
-        }
-
-
                 # ARTIST PHOTO MODEL
 class Photo(db.Model):
     __tablename__ = "photo"
 
     id = db.Column(db.Integer, primary_key=True)
     title = db.Column(db.String(100), nullable=False)
-    media_url = db.Column(db.Text, nullable=False, unique=True)  # Cloudinary URL
+    media_url = db.Column(db.Text, nullable=False)  # Cloudinary URL
 
+    # Relationships
     artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
 
     def __repr__(self):
@@ -119,15 +82,17 @@ def serialize(self):
             "media_url": self.media_url
         }
 
+
                 # ARTIST VIDEO MODEL
 class Video(db.Model):
     __tablename__ = "video"
 
     id = db.Column(db.Integer, primary_key=True)
     title = db.Column(db.String(100), nullable=False)
-    media_url = db.Column(db.Text, nullable=False, unique=True)  # Cloudinary URL
+    media_url = db.Column(db.Text, nullable=False)  # Cloudinary URL
     duration = db.Column(db.Integer, nullable=False)
 
+    # Relationships
     artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
 
     def __repr__(self):
@@ -147,9 +112,10 @@ class Music(db.Model):
 
     id = db.Column(db.Integer, primary_key=True)
     title = db.Column(db.String(200), nullable=False)
-    media_url = db.Column(db.Text, nullable=False, unique=True)  # Cloudinary URL
+    media_url = db.Column(db.Text, nullable=False)  # Cloudinary URL
     duration = db.Column(db.Integer, nullable=False)
 
+    # Relationships
     artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
 
     def __repr__(self):
@@ -164,32 +130,14 @@ def serialize(self):
         }
 
 
-                # USER SAVED MUSIC & SAVED ARTISTS MODEL
-class Saved_Artist(db.Model):
-    __tablename__ = "saved_artist"
-
-    id = db.Column(db.Integer, primary_key=True)
-
-    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"))
-
-    def __repr__(self):
-        return f'<Saved_Artist {self.artist_id}>'
-
-    def serialize(self):
-        return {
-            "id": self.id,
-            "user_id": self.user_id,
-            "artist_id": self.artist_id
-        }
-
+            # USER SAVED MUSIC & FOLLOW ARTIST MODEL
 class Saved_Music(db.Model):
     __tablename__ = "saved_music"
 
     id = db.Column(db.Integer, primary_key=True)
 
+    # Relationships
     user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"))
     music_id = db.Column(db.Integer, db.ForeignKey("music.id"))
 
     def __repr__(self):
@@ -199,7 +147,6 @@ def serialize(self):
         return {
             "id": self.id,
             "user_id": self.user_id,
-            "artist_id": self.artist_id,
             "music_id": self.music_id
         }
     
@@ -211,8 +158,6 @@ class Follow_Artist(db.Model):
     user_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
     artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), primary_key=True)
 
-    is_active = db.Column(db.Boolean, default=True)
-
     def __repr__(self):
         return f'<Follow_Artist user_id={self.user_id}, artist_id={self.artist_id}, is_active={self.is_active}>'
 
@@ -220,5 +165,4 @@ def serialize(self):
         return {
             "user_id": self.user_id,
             "artist_id": self.artist_id,
-            "is_active": self.is_active
         }
\ No newline at end of file

From 54984ce435f1714ea636ddeabdd77afc7c5258fb Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Thu, 6 Mar 2025 10:55:55 +0000
Subject: [PATCH 17/25] Database Model user modified

---
 src/api/models.py | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/src/api/models.py b/src/api/models.py
index bffd963213..a3c186c5cb 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -1,5 +1,6 @@
 from flask_sqlalchemy import SQLAlchemy
 
+
 db = SQLAlchemy()
 
         #  USER REGISTER AND PROFILE MODEL
@@ -8,13 +9,15 @@ class User(db.Model):
 
     id = db.Column(db.Integer, primary_key=True)
 
-    full_name = db.Column(db.String(120), unique=True, nullable=True)
+    fullName = db.Column(db.String(120), unique=True, nullable=True)
     username = db.Column(db.String(120), unique=True, nullable=True)
+    address = db.Column(db.String(120), unique=True, nullable=False)
 
     email = db.Column(db.String(120), unique=True, nullable=False)
-    password = db.Column(db.String(80), unique=False, nullable=False)
+    password_hash = db.Column(db.String(512), unique=False, nullable=False)
 
     is_artist = db.Column(db.Boolean, default=False) # Check if account is artist
+    is_active = db.Column(db.Boolean(), default=True)
     profile_photo = db.Column(db.String(255), nullable=True)  # Profile photo URL
 
     #  Relationships
@@ -23,17 +26,31 @@ class User(db.Model):
 
     def __repr__(self):
         return f'<User {self.username}>'
+    
+    def artist(is_artist):
+        if is_artist:
+            return "Si"
+        else:
+            return "No"
 
     def serialize(self):
         return {
             "id": self.id,
-            "full_name": self.full_name,
+            "full_name": self.fullName,
             "username": self.username,
             "email": self.email,
-            "is_artist": self.is_artist,
+            "address":self.address,
+            "artist":self.artist(),
             "profile_photo": self.profile_photo,
         }
 
+def set_password(self, password):
+    self.password_hash = generate_password_hash(password)
+
+def check_password(self,password):
+    return check_password_hash(self.password_hash,password)
+
+
         # ARTIST PROFILE MODEL
 class Artist_Profile(db.Model):
     __tablename__ = "artist_profile"

From 911fbfc7f6d7f12499b7f8363f1e03cc1e8671ad Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Thu, 6 Mar 2025 14:14:05 +0000
Subject: [PATCH 18/25] Last commit I promise

---
 src/api/models.py | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/api/models.py b/src/api/models.py
index 9e53b9a66b..716924a36c 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -60,11 +60,11 @@ class Artist_Profile(db.Model):
     bio = db.Column(db.Text, nullable=True)
 
     # Relationships
-    artist_id = db.Column(db.Integer, db.ForeignKey('users.id'), unique=True, nullable=False)
+    artist_id = db.Column(db.Integer, db.ForeignKey('user.id'), unique=True, nullable=False)
 
-    artist_photos = db.relationship("Photo", backref="artist")
-    artist_videos = db.relationship("Video", backref="artist")
-    artist_music = db.relationship("Music", backref="artist")
+    artist_photos = db.relationship("Photo", backref="artist_profile")
+    artist_videos = db.relationship("Video", backref="artist_profile")
+    artist_music = db.relationship("Music", backref="artist_profile")
 
     def __repr__(self):
         return f'<Artist_Profile {self.id}>'
@@ -88,7 +88,7 @@ class Photo(db.Model):
     media_url = db.Column(db.Text, nullable=False)  # Cloudinary URL
 
     # Relationships
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), nullable=False)
 
     def __repr__(self):
         return f'<Photo {self.title}>'
@@ -111,7 +111,7 @@ class Video(db.Model):
     duration = db.Column(db.Integer, nullable=False)
 
     # Relationships
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), nullable=False)
 
     def __repr__(self):
         return f'<Video {self.title}>'
@@ -149,7 +149,7 @@ class Music(db.Model):
     duration = db.Column(db.Integer, nullable=False)
 
     # Relationships
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), nullable=False)
 
     def __repr__(self):
         return f'<Music {self.title}>'
@@ -189,7 +189,7 @@ class Follow_Artist(db.Model):
     __tablename__ = "follow_artist"
 
     user_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), primary_key=True)
+    artist_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), primary_key=True)
 
     def __repr__(self):
         return f'<Follow_Artist user_id={self.user_id}, artist_id={self.artist_id}, is_active={self.is_active}>'

From 9587dfee19c401b95e95da545e341c667e8e2115 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Fri, 7 Mar 2025 18:41:30 +0000
Subject: [PATCH 19/25] Created videos routes

---
 Pipfile.lock      | 653 +---------------------------------------------
 src/api/routes.py |  69 ++++-
 2 files changed, 70 insertions(+), 652 deletions(-)

diff --git a/Pipfile.lock b/Pipfile.lock
index 35fcf34ad2..453d225727 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,11 +1,7 @@
 {
     "_meta": {
         "hash": {
-
-            "sha256": "df7144212363e2fb107242f0448476de13fa283a57b574ff560e2a499fbc4049"
-
-            "sha256": "565f98e9600186b666ea99818452df31f2af6834fd198eaf1fcc557fed5d866b"
-
+            "sha256": "f330cd23b0270ece3f391c1a9745b0587e3adc87478d87f3d8a1e118c43e72c3"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -19,651 +15,6 @@
             }
         ]
     },
-    "default": {
-        "alembic": {
-            "hashes": [
-                "sha256:197de710da4b3e91cf66a826a5b31b5d59a127ab41bd0fc42863e2902ce2bbbe",
-                "sha256:e1a1c738577bca1f27e68728c910cd389b9a92152ff91d902da649c192e30c49"
-            ],
-            "markers": "python_version >= '3.9'",
-            "version": "==1.15.1"
-        },
-        "blinker": {
-            "hashes": [
-                "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf",
-                "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"
-            ],
-            "markers": "python_version >= '3.9'",
-            "version": "==1.9.0"
-        },
-        "certifi": {
-            "hashes": [
-                "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651",
-                "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"
-            ],
-            "markers": "python_version >= '3.6'",
-            "version": "==2025.1.31"
-        },
-        "charset-normalizer": {
-            "hashes": [
-                "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537",
-                "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa",
-                "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a",
-                "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294",
-                "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b",
-                "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd",
-                "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601",
-                "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd",
-                "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4",
-                "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d",
-                "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2",
-                "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313",
-                "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd",
-                "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa",
-                "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8",
-                "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1",
-                "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2",
-                "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496",
-                "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d",
-                "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b",
-                "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e",
-                "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a",
-                "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4",
-                "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca",
-                "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78",
-                "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408",
-                "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5",
-                "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3",
-                "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f",
-                "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a",
-                "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765",
-                "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6",
-                "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146",
-                "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6",
-                "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9",
-                "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd",
-                "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c",
-                "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f",
-                "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545",
-                "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176",
-                "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770",
-                "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824",
-                "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f",
-                "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf",
-                "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487",
-                "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d",
-                "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd",
-                "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b",
-                "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534",
-                "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f",
-                "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b",
-                "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9",
-                "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd",
-                "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125",
-                "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9",
-                "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de",
-                "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11",
-                "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d",
-                "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35",
-                "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f",
-                "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda",
-                "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7",
-                "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a",
-                "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971",
-                "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8",
-                "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41",
-                "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d",
-                "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f",
-                "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757",
-                "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a",
-                "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886",
-                "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77",
-                "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76",
-                "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247",
-                "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85",
-                "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb",
-                "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7",
-                "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e",
-                "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6",
-                "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037",
-                "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1",
-                "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e",
-                "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807",
-                "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407",
-                "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c",
-                "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12",
-                "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3",
-                "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089",
-                "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd",
-                "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e",
-                "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00",
-                "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"
-            ],
-            "markers": "python_version >= '3.7'",
-            "version": "==3.4.1"
-        },
-        "click": {
-            "hashes": [
-                "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2",
-                "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"
-            ],
-            "markers": "python_version >= '3.7'",
-            "version": "==8.1.8"
-        },
-        "cloudinary": {
-            "hashes": [
-                "sha256:ba223705409b2aaddd5196c2184d65f50a83dffcba3b94f3727658ff6a0172a3",
-                "sha256:e4191b470c5bae55542b64e0a78659af42971880294456dca480bc974fa9280a"
-            ],
-            "index": "pypi",
-            "version": "==1.42.2"
-        },
-        "flask": {
-            "hashes": [
-                "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac",
-                "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136"
-            ],
-            "index": "pypi",
-            "version": "==3.1.0"
-        },
-        "flask-admin": {
-            "hashes": [
-                "sha256:24cae2af832b6a611a01d7dc35f42d266c1d6c75a426b869d8cb241b78233369",
-                "sha256:fd8190f1ec3355913a22739c46ed3623f1d82b8112cde324c60a6fc9b21c9406"
-            ],
-            "index": "pypi",
-            "version": "==1.6.1"
-        },
-        "flask-cors": {
-            "hashes": [
-                "sha256:6ccb38d16d6b72bbc156c1c3f192bc435bfcc3c2bc864b2df1eb9b2d97b2403c",
-                "sha256:fa5cb364ead54bbf401a26dbf03030c6b18fb2fcaf70408096a572b409586b0c"
-
-            ],
-            "index": "pypi",
-            "version": "==5.0.1"
-        },
-        "flask-extended": {
-            "hashes": [
-                "sha256:7d4951573da1fb680185970bfb6427934809ddd4a7d372acf67736d4455ae7be",
-                "sha256:dcf785327209e1967b01e62868f3ff6bc1401a2359746972111969dc16a7fd29"
-            ],
-            "index": "pypi",
-            "version": "==0.2"
-            ],
-            "index": "pypi",
-            "version": "==5.0.1"
-        },
-        "flask-jwt-extended": {
-            "hashes": [
-                "sha256:52f35bf0985354d7fb7b876e2eb0e0b141aaff865a22ff6cc33d9a18aa987978",
-                "sha256:8085d6757505b6f3291a2638c84d207e8f0ad0de662d1f46aa2f77e658a0c976"
-            ],
-            "index": "pypi",
-            "version": "==4.7.1"
-        },
-        "flask-migrate": {
-            "hashes": [
-                "sha256:1a336b06eb2c3ace005f5f2ded8641d534c18798d64061f6ff11f79e1434126d",
-                "sha256:24d8051af161782e0743af1b04a152d007bad9772b2bca67b7ec1e8ceeb3910d"
-            ],
-            "index": "pypi",
-            "version": "==4.1.0"
-        },
-        "flask-sqlalchemy": {
-            "hashes": [
-                "sha256:c5765e58ca145401b52106c0f46178569243c5da25556be2c231ecc60867c5b1",
-                "sha256:cabb6600ddd819a9f859f36515bb1bd8e7dbf30206cc679d2b081dff9e383283"
-            ],
-            "index": "pypi",
-            "version": "==3.0.5"
-        },
-        "flask-swagger": {
-            "hashes": [
-                "sha256:3caddb1311388eafc86f82f8e64ba386a5df6b84e5f16dfae19ca08173eba216",
-                "sha256:b4085f5bc36df4c20b6548cd1413adc9cf35719b0f0695367cd542065145294d"
-            ],
-            "index": "pypi",
-            "version": "==0.2.14"
-        },
-        "greenlet": {
-            "hashes": [
-                "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e",
-                "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7",
-                "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01",
-                "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1",
-                "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159",
-                "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563",
-                "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83",
-                "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9",
-                "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395",
-                "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa",
-                "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942",
-                "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1",
-                "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441",
-                "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22",
-                "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9",
-                "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0",
-                "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba",
-                "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3",
-                "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1",
-                "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6",
-                "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291",
-                "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39",
-                "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d",
-                "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467",
-                "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475",
-                "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef",
-                "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c",
-                "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511",
-                "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c",
-                "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822",
-                "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a",
-                "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8",
-                "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d",
-                "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01",
-                "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145",
-                "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80",
-                "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13",
-                "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e",
-                "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b",
-                "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1",
-                "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef",
-                "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc",
-                "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff",
-                "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120",
-                "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437",
-                "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd",
-                "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981",
-                "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36",
-                "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a",
-                "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798",
-                "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7",
-                "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761",
-                "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0",
-                "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e",
-                "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af",
-                "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa",
-                "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c",
-                "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42",
-                "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e",
-                "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81",
-                "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e",
-                "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617",
-                "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc",
-                "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de",
-                "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111",
-                "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383",
-                "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70",
-                "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6",
-                "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4",
-                "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011",
-                "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803",
-                "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79",
-                "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f"
-            ],
-            "markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))",
-            "version": "==3.1.1"
-        },
-        "gunicorn": {
-            "hashes": [
-                "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d",
-                "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"
-            ],
-            "index": "pypi",
-            "version": "==23.0.0"
-        },
-        "idna": {
-            "hashes": [
-                "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
-                "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
-            ],
-            "markers": "python_version >= '3.6'",
-            "version": "==3.10"
-        },
-        "itsdangerous": {
-            "hashes": [
-                "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
-                "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"
-            ],
-            "markers": "python_version >= '3.8'",
-            "version": "==2.2.0"
-        },
-        "jinja2": {
-            "hashes": [
-                "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb",
-                "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"
-            ],
-            "markers": "python_version >= '3.7'",
-            "version": "==3.1.5"
-        },
-        "mako": {
-            "hashes": [
-                "sha256:95920acccb578427a9aa38e37a186b1e43156c87260d7ba18ca63aa4c7cbd3a1",
-                "sha256:b5d65ff3462870feec922dbccf38f6efb44e5714d7b593a656be86663d8600ac"
-            ],
-            "markers": "python_version >= '3.8'",
-            "version": "==1.3.9"
-        },
-        "markupsafe": {
-            "hashes": [
-                "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4",
-                "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30",
-                "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0",
-                "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9",
-                "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396",
-                "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13",
-                "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028",
-                "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca",
-                "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557",
-                "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832",
-                "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0",
-                "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b",
-                "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579",
-                "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a",
-                "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c",
-                "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff",
-                "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c",
-                "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22",
-                "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094",
-                "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb",
-                "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e",
-                "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5",
-                "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a",
-                "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d",
-                "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a",
-                "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b",
-                "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8",
-                "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225",
-                "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c",
-                "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144",
-                "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f",
-                "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87",
-                "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d",
-                "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93",
-                "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf",
-                "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158",
-                "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84",
-                "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb",
-                "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48",
-                "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171",
-                "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c",
-                "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6",
-                "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd",
-                "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d",
-                "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1",
-                "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d",
-                "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca",
-                "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a",
-                "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29",
-                "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe",
-                "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798",
-                "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c",
-                "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8",
-                "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f",
-                "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f",
-                "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a",
-                "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178",
-                "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0",
-                "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79",
-                "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430",
-                "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"
-            ],
-            "markers": "python_version >= '3.9'",
-            "version": "==3.0.2"
-        },
-        "packaging": {
-            "hashes": [
-                "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
-                "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"
-            ],
-            "markers": "python_version >= '3.8'",
-            "version": "==24.2"
-        },
-        "psycopg2-binary": {
-            "hashes": [
-                "sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff",
-                "sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5",
-                "sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f",
-                "sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5",
-                "sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0",
-                "sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c",
-                "sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c",
-                "sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341",
-                "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f",
-                "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7",
-                "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d",
-                "sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007",
-                "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142",
-                "sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92",
-                "sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb",
-                "sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5",
-                "sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5",
-                "sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8",
-                "sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1",
-                "sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68",
-                "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73",
-                "sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1",
-                "sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53",
-                "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d",
-                "sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906",
-                "sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0",
-                "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2",
-                "sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a",
-                "sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b",
-                "sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44",
-                "sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648",
-                "sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7",
-                "sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f",
-                "sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa",
-                "sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697",
-                "sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d",
-                "sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b",
-                "sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526",
-                "sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4",
-                "sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287",
-                "sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e",
-                "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673",
-                "sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0",
-                "sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30",
-                "sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3",
-                "sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e",
-                "sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92",
-                "sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a",
-                "sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c",
-                "sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8",
-                "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909",
-                "sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47",
-                "sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864",
-                "sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc",
-                "sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00",
-                "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb",
-                "sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539",
-                "sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b",
-                "sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481",
-                "sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5",
-                "sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4",
-                "sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64",
-                "sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392",
-                "sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4",
-                "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1",
-                "sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1",
-                "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567",
-                "sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863"
-            ],
-            "index": "pypi",
-            "version": "==2.9.10"
-        },
-        "pyjwt": {
-            "hashes": [
-                "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850",
-                "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"
-            ],
-            "index": "pypi",
-            "version": "==2.9.0"
-        },
-        "python-dotenv": {
-            "hashes": [
-                "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca",
-                "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"
-            ],
-            "index": "pypi",
-            "version": "==1.0.1"
-        },
-        "pyyaml": {
-            "hashes": [
-                "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff",
-                "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48",
-                "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086",
-                "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e",
-                "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133",
-                "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5",
-                "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484",
-                "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee",
-                "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5",
-                "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68",
-                "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a",
-                "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf",
-                "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99",
-                "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8",
-                "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85",
-                "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19",
-                "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc",
-                "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a",
-                "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1",
-                "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317",
-                "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c",
-                "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631",
-                "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d",
-                "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652",
-                "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5",
-                "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e",
-                "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b",
-                "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8",
-                "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476",
-                "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706",
-                "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563",
-                "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237",
-                "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b",
-                "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083",
-                "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180",
-                "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425",
-                "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e",
-                "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f",
-                "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725",
-                "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183",
-                "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab",
-                "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774",
-                "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725",
-                "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e",
-                "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5",
-                "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d",
-                "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290",
-                "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44",
-                "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed",
-                "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4",
-                "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba",
-                "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12",
-                "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"
-            ],
-            "markers": "python_version >= '3.8'",
-            "version": "==6.0.2"
-        },
-        "requests": {
-            "hashes": [
-                "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
-                "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"
-            ],
-            "index": "pypi",
-            "version": "==2.32.3"
-        },
-        "six": {
-            "hashes": [
-                "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
-                "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
-            ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==1.17.0"
-        },
-        "sqlalchemy": {
-            "hashes": [
-                "sha256:07e48cbcdda6b8bc7a59d6728bd3f5f574ffe03f2c9fb384239f3789c2d95c2e",
-                "sha256:18cafdb27834fa03569d29f571df7115812a0e59fd6a3a03ccb0d33678ec8420",
-                "sha256:1b1e5e96e2789d89f023d080bee432e2fef64d95857969e70d3cadec80bd26f0",
-                "sha256:315676344e3558f1f80d02535f410e80ea4e8fddba31ec78fe390eff5fb8f466",
-                "sha256:31de1e2c45e67a5ec1ecca6ec26aefc299dd5151e355eb5199cd9516b57340be",
-                "sha256:3d94682732d1a0def5672471ba42a29ff5e21bb0aae0afa00bb10796fc1e28dd",
-                "sha256:3ec187acf85984263299a3f15c34a6c0671f83565d86d10f43ace49881a82718",
-                "sha256:4847f4b1d822754e35707db913396a29d874ee77b9c3c3ef3f04d5a9a6209618",
-                "sha256:4d112b0f3c1bc5ff70554a97344625ef621c1bfe02a73c5d97cac91f8cd7a41e",
-                "sha256:51e1ba2884c6a2b8e19109dc08c71c49530006c1084156ecadfaadf5f9b8b053",
-                "sha256:535377e9b10aff5a045e3d9ada8a62d02058b422c0504ebdcf07930599890eb0",
-                "sha256:5dbf17ac9a61e7a3f1c7ca47237aac93cabd7f08ad92ac5b96d6f8dea4287fc1",
-                "sha256:5f752676fc126edc1c4af0ec2e4d2adca48ddfae5de46bb40adbd3f903eb2120",
-                "sha256:64cb0ad8a190bc22d2112001cfecdec45baffdf41871de777239da6a28ed74b6",
-                "sha256:6913b8247d8a292ef8315162a51931e2b40ce91681f1b6f18f697045200c4a30",
-                "sha256:69fac0a7054d86b997af12dc23f581cf0b25fb1c7d1fed43257dee3af32d3d6d",
-                "sha256:7001f16a9a8e06488c3c7154827c48455d1c1507d7228d43e781afbc8ceccf6d",
-                "sha256:7b81b1030c42b003fc10ddd17825571603117f848814a344d305262d370e7c34",
-                "sha256:7f8267682eb41a0584cf66d8a697fef64b53281d01c93a503e1344197f2e01fe",
-                "sha256:887865924c3d6e9a473dc82b70977395301533b3030d0f020c38fd9eba5419f2",
-                "sha256:9167d4227b56591a4cc5524f1b79ccd7ea994f36e4c648ab42ca995d28ebbb96",
-                "sha256:939f9a018d2ad04036746e15d119c0428b1e557470361aa798e6e7d7f5875be0",
-                "sha256:955162ad1a931fe416eded6bb144ba891ccbf9b2e49dc7ded39274dd9c5affc5",
-                "sha256:984ee13543a346324319a1fb72b698e521506f6f22dc37d7752a329e9cd00a32",
-                "sha256:9883f5fae4fd8e3f875adc2add69f8b945625811689a6c65866a35ee9c0aea23",
-                "sha256:a1ad90c97029cc3ab4ffd57443a20fac21d2ec3c89532b084b073b3feb5abff3",
-                "sha256:a3714e5b33226131ac0da60d18995a102a17dddd42368b7bdd206737297823ad",
-                "sha256:ae067ab639fa499f67ded52f5bc8e084f045d10b5ac7bb928ae4ca2b6c0429a5",
-                "sha256:b33ffbdbbf5446cf36cd4cc530c9d9905d3c2fe56ed09e25c22c850cdb9fac92",
-                "sha256:b6e4cb5c63f705c9d546a054c60d326cbde7421421e2d2565ce3e2eee4e1a01f",
-                "sha256:b7f4b6aa6e87991ec7ce0e769689a977776db6704947e562102431474799a857",
-                "sha256:c04144a24103135ea0315d459431ac196fe96f55d3213bfd6d39d0247775c854",
-                "sha256:c522e496f9b9b70296a7675272ec21937ccfc15da664b74b9f58d98a641ce1b6",
-                "sha256:c5a99282848b6cae0056b85da17392a26b2d39178394fc25700bcf967e06e97a",
-                "sha256:c7a46639ba058d320c9f53a81db38119a74b8a7a1884df44d09fbe807d028aaf",
-                "sha256:d4b1cc7835b39835c75cf7c20c926b42e97d074147c902a9ebb7cf2c840dc4e2",
-                "sha256:d4d164df3d83d204c69f840da30b292ac7dc54285096c6171245b8d7807185aa",
-                "sha256:d61e9ecc849d8d44d7f80894ecff4abe347136e9d926560b818f6243409f3c86",
-                "sha256:d68e1762997bfebf9e5cf2a9fd0bcf9ca2fdd8136ce7b24bbd3bbfa4328f3e4a",
-                "sha256:e3c1808008124850115a3f7e793a975cfa5c8a26ceeeb9ff9cbb4485cac556df",
-                "sha256:f8cb80fe8d14307e4124f6fad64dfd87ab749c9d275f82b8b4ec84c84ecebdbe"
-            ],
-            "index": "pypi",
-            "version": "==1.4.46"
-        },
-        "typing-extensions": {
-            "hashes": [
-                "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d",
-                "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"
-            ],
-            "index": "pypi",
-            "version": "==4.12.2"
-        },
-        "urllib3": {
-            "hashes": [
-                "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df",
-                "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"
-            ],
-            "markers": "python_version >= '3.9'",
-            "version": "==2.3.0"
-        },
-        "werkzeug": {
-            "hashes": [
-                "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e",
-                "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"
-            ],
-            "markers": "python_version >= '3.9'",
-            "version": "==3.1.3"
-        },
-        "wtforms": {
-            "hashes": [
-                "sha256:bf831c042829c8cdbad74c27575098d541d039b1faa74c771545ecac916f2c07",
-                "sha256:f8d76180d7239c94c6322f7990ae1216dae3659b7aa1cee94b6318bdffb474b9"
-            ],
-            "index": "pypi",
-            "version": "==3.1.2"
-        }
-    },
+    "default": {},
     "develop": {}
 }
diff --git a/src/api/routes.py b/src/api/routes.py
index 96046518c9..bfceae764f 100644
--- a/src/api/routes.py
+++ b/src/api/routes.py
@@ -2,7 +2,7 @@
 This module takes care of starting the API Server, Loading the DB and Adding the endpoints
 """
 from flask import Flask, request, jsonify, url_for, Blueprint
-from api.models import db, User, Genre
+from api.models import db, User, Genre, ArtistProfile, Photo, Video, Music, SavedMusic, FollowArtist
 from api.utils import generate_sitemap, APIException
 from flask_cors import CORS
 import os
@@ -115,3 +115,70 @@ def getGenres():
     genres = Genre.query.filter(Genre.id != 0).all()
     return jsonify({"genres": [genre.serialize() for genre in genres]}), 200
 
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET: Obtener videos
+@api.route('/artist/<int:artist_id>/videos', methods=['GET'])
+def get_artist_videos(artist_id):
+    # Verifica si el artista existe (descomenta o ajusta según tu modelo real)
+    artist = ArtistProfile.query.get(artist_id)
+    if not artist:
+        return jsonify({"msg": "Artista no encontrado"}), 404
+
+    # Obtén los videos para este artista
+    videos = Video.query.filter_by(artist_id=artist_id).all()
+    serialized_videos = [v.serialize() for v in videos]
+    return jsonify(serialized_videos), 200
+
+ # POST: Guardar nuevo video
+@api.route('/artist/<int:artist_id>/videos', methods=['POST'])
+def create_artist_video(artist_id):
+    artist = ArtistProfile.query.get(artist_id)
+    if not artist:
+        return jsonify({"msg": "Artista no encontrado"}), 404
+
+    body = request.get_json()
+    if not body:
+        return jsonify({"msg": "No data provided"}), 400
+
+    media_url = body.get("media_url")
+    title = body.get("title", "Sin título")
+
+    if not media_url:
+        return jsonify({"msg": "media_url is required"}), 400
+
+    # Creamos el video
+    new_video = Video(
+        title=title,
+        media_url=media_url,
+        artist_id=artist_id
+    )
+    db.session.add(new_video)
+    db.session.commit()
+
+    return jsonify(new_video.serialize()), 201
+
+ # DELETE: Eliminar video 
+@api.route('/artist/<int:artist_id>/videos/<int:video_id>', methods=['DELETE'])
+def delete_artist_video(artist_id, video_id):
+    artist = ArtistProfile.query.get(artist_id)
+    if not artist:
+        return jsonify({"msg": "Artista no encontrado"}), 404
+
+    video = Video.query.filter_by(id=video_id, artist_id=artist_id).first()
+    if not video:
+        return jsonify({"msg": "Video no encontrado"}), 404
+
+    db.session.delete(video)
+    db.session.commit()
+    return jsonify({"msg": "Video eliminado con éxito"}), 200

From a6f5a873a6dae8ef74310e5fd3958bf7c346008f Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Fri, 7 Mar 2025 20:06:28 +0000
Subject: [PATCH 20/25] Music routes created

---
 src/api/routes.py | 68 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 60 insertions(+), 8 deletions(-)

diff --git a/src/api/routes.py b/src/api/routes.py
index bfceae764f..19a3d3bcd0 100644
--- a/src/api/routes.py
+++ b/src/api/routes.py
@@ -96,6 +96,7 @@ def generate_token():
 def get_current_user():
     return jsonify(current_user.serialize()), 200
 
+
 # ROUTE TO LOAD GENRES
 @api.route('/getGenresapi', methods=["GET"])
 def getGenresApi():
@@ -119,14 +120,6 @@ def getGenres():
 
 
 
-
-
-
-
-
-
-
-
  # GET: Obtener videos
 @api.route('/artist/<int:artist_id>/videos', methods=['GET'])
 def get_artist_videos(artist_id):
@@ -182,3 +175,62 @@ def delete_artist_video(artist_id, video_id):
     db.session.delete(video)
     db.session.commit()
     return jsonify({"msg": "Video eliminado con éxito"}), 200
+
+
+
+
+ # GET: Obtener musica
+@api.route('/artist/<int:artist_id>/songs', methods=['GET'])
+def get_artist_songs(artist_id):
+    # Verifica si el artista existe (descomenta o ajusta según tu modelo real)
+    artist = ArtistProfile.query.get(artist_id)
+    if not artist:
+        return jsonify({"msg": "Artista no encontrado"}), 404
+
+    # Obtén la musica para este artista
+    songs = Music.query.filter_by(artist_id=artist_id).all()
+    serialized_songs = [s.serialize() for s in songs]
+    return jsonify(serialized_songs), 200
+
+ # POST: Guardar nueva musica
+@api.route('/artist/<int:artist_id>/songs', methods=['POST'])
+def create_artist_song(artist_id):
+    artist = ArtistProfile.query.get(artist_id)
+    if not artist:
+        return jsonify({"msg": "Artista no encontrado"}), 404
+
+    body = request.get_json()
+    if not body:
+        return jsonify({"msg": "No data provided"}), 400
+
+    media_url = body.get("media_url")
+    title = body.get("title", "Sin título")
+
+    if not media_url:
+        return jsonify({"msg": "media_url is required"}), 400
+
+    # Creamos la musica
+    new_song = Music(
+        title=title,
+        media_url=media_url,
+        artist_id=artist_id
+    )
+    db.session.add(new_song)
+    db.session.commit()
+
+    return jsonify(new_song.serialize()), 201
+
+ # DELETE: Eliminar musica 
+@api.route('/artist/<int:artist_id>/songs/<int:song_id>', methods=['DELETE'])
+def delete_artist_song(artist_id, song_id):
+    artist = ArtistProfile.query.get(artist_id)
+    if not artist:
+        return jsonify({"msg": "Artista no encontrado"}), 404
+
+    song = Music.query.filter_by(id=song_id, artist_id=artist_id).first()
+    if not song:
+        return jsonify({"msg": "Cancion no encontrada"}), 404
+
+    db.session.delete(song)
+    db.session.commit()
+    return jsonify({"msg": "Cancion eliminada con éxito"}), 200
\ No newline at end of file

From 834e1f99ee62297dd5a2f08e84eb859699d3e051 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Sat, 8 Mar 2025 15:03:20 +0000
Subject: [PATCH 21/25] Footer done

---
 .vscode/settings.json            |  3 +++
 src/api/models.py                | 10 +++++-----
 src/front/js/component/footer.js | 16 ++++++++--------
 src/front/js/pages/home.js       | 13 -------------
 src/front/styles/footer.css      | 12 ++++++++++++
 5 files changed, 28 insertions(+), 26 deletions(-)
 create mode 100644 src/front/styles/footer.css

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7bd07e2e82..6e34222a2e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -6,5 +6,8 @@
     },
     "[javascript]": {
         "editor.defaultFormatter": "vscode.typescript-language-features"
+    },
+    "[css]": {
+        "editor.defaultFormatter": "vscode.css-language-features"
     }
 }
diff --git a/src/api/models.py b/src/api/models.py
index 716924a36c..dd7b1d8e06 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -22,8 +22,8 @@ class User(db.Model):
     profile_photo = db.Column(db.String(255), nullable=True)  # Profile photo URL
 
     #  Relationships
-    followed_artists = db.relationship('Follow_Artist', backref='follow_artist')
-    saved_music = db.relationship('Saved_Music', backref='user')
+    followed_artists = db.relationship('FollowArtist', backref='follow_artist')
+    saved_music = db.relationship('SavedMusic', backref='user')
 
     def __repr__(self):
         return f'<User {self.username}>'
@@ -53,7 +53,7 @@ def check_password(self,password):
 
 
         # ARTIST PROFILE MODEL
-class Artist_Profile(db.Model):
+class ArtistProfile(db.Model):
     __tablename__ = "artist_profile"
 
     id = db.Column(db.Integer, primary_key=True)
@@ -164,7 +164,7 @@ def serialize(self):
 
 
             # USER SAVED MUSIC & FOLLOW ARTIST MODEL
-class Saved_Music(db.Model):
+class SavedMusic(db.Model):
     __tablename__ = "saved_music"
 
     id = db.Column(db.Integer, primary_key=True)
@@ -185,7 +185,7 @@ def serialize(self):
     
 
                 # FOLLOW ARTIST MODEL
-class Follow_Artist(db.Model):
+class FollowArtist(db.Model):
     __tablename__ = "follow_artist"
 
     user_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
diff --git a/src/front/js/component/footer.js b/src/front/js/component/footer.js
index 670323e091..a0a8032668 100755
--- a/src/front/js/component/footer.js
+++ b/src/front/js/component/footer.js
@@ -1,10 +1,10 @@
 import React, { Component } from "react";
+import "../../styles/footer.css";
 
-export const Footer = () => (
-	<footer className="footer mt-auto py-3 text-center">
-		<p>
-			Made with <i className="fa fa-heart text-danger" /> by{" "}
-			<a href="http://www.4geeksacademy.com">4Geeks Academy</a>
-		</p>
-	</footer>
-);
+export const Footer = () => {
+	return (
+		<footer className="footer">
+			<p className="text">&copy; 2025 SoundCript. All Rights Reserved.</p>
+		</footer>
+	)
+};
diff --git a/src/front/js/pages/home.js b/src/front/js/pages/home.js
index 7b0be46a1e..458bd892f1 100755
--- a/src/front/js/pages/home.js
+++ b/src/front/js/pages/home.js
@@ -8,19 +8,6 @@ export const Home = () => {
 
 	return (
 		<div className="text-center mt-5">
-			<h1>Hello Rigo!!</h1>
-			<p>
-				<img src={rigoImageUrl} />
-			</p>
-			<div className="alert alert-info">
-				{store.message || "Loading message from the backend (make sure your python backend is running)..."}
-			</div>
-			<p>
-				This boilerplate comes with lots of documentation:{" "}
-				<a href="https://start.4geeksacademy.com/starters/react-flask">
-					Read documentation
-				</a>
-			</p>
 		</div>
 	);
 };
diff --git a/src/front/styles/footer.css b/src/front/styles/footer.css
new file mode 100644
index 0000000000..86da241e79
--- /dev/null
+++ b/src/front/styles/footer.css
@@ -0,0 +1,12 @@
+.footer {
+    width: 100%;
+    margin-top: 3%;
+    border-radius: 10px;
+    display: grid;
+    place-items: center;
+    height: 6%;
+    background: linear-gradient(90deg,
+            var(--color-red) 0%,
+            var(--color-giants-orange) 50%,
+            var(--color-atomic-tangerine) 100%);
+}

From da49249ae4656eaafbed3ed54df5843a2d23a690 Mon Sep 17 00:00:00 2001
From: Rafael Salinas Gonzalez <rafsalgon@gmail.com>
Date: Mon, 10 Mar 2025 14:14:46 +0000
Subject: [PATCH 22/25] SavedSong, FollowArtist and GET user favourite routes
 created + Music model modified to Song

---
 src/api/models.py | 28 +++++++-------
 src/api/routes.py | 94 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 102 insertions(+), 20 deletions(-)

diff --git a/src/api/models.py b/src/api/models.py
index dd7b1d8e06..0cba1aee0a 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -22,8 +22,8 @@ class User(db.Model):
     profile_photo = db.Column(db.String(255), nullable=True)  # Profile photo URL
 
     #  Relationships
-    followed_artists = db.relationship('FollowArtist', backref='follow_artist')
-    saved_music = db.relationship('SavedMusic', backref='user')
+    followed_artist = db.relationship('FollowArtist', backref='follow_artist')
+    saved_song = db.relationship('SavedSong', backref='user')
 
     def __repr__(self):
         return f'<User {self.username}>'
@@ -64,10 +64,10 @@ class ArtistProfile(db.Model):
 
     artist_photos = db.relationship("Photo", backref="artist_profile")
     artist_videos = db.relationship("Video", backref="artist_profile")
-    artist_music = db.relationship("Music", backref="artist_profile")
+    artist_songs = db.relationship("Song", backref="artist_profile")
 
     def __repr__(self):
-        return f'<Artist_Profile {self.id}>'
+        return f'<ArtistProfile {self.id}>'
 
     def serialize(self):
         return {
@@ -76,7 +76,7 @@ def serialize(self):
             "bio": self.bio,
             "artist_photos": self.artist_photos,
             "artist_videos": self.artist_videos,
-            "artist_music": self.artist_music
+            "artist_songs": self.artist_songs
         }
     
                 # ARTIST PHOTO MODEL
@@ -140,8 +140,8 @@ def serialize(self):
         }
       
                 # ARTIST MUSIC MODEL
-class Music(db.Model):
-    __tablename__ = "music"
+class Song(db.Model):
+    __tablename__ = "song"
 
     id = db.Column(db.Integer, primary_key=True)
     title = db.Column(db.String(200), nullable=False)
@@ -152,7 +152,7 @@ class Music(db.Model):
     artist_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), nullable=False)
 
     def __repr__(self):
-        return f'<Music {self.title}>'
+        return f'<Song {self.title}>'
 
     def serialize(self):
         return {
@@ -164,23 +164,23 @@ def serialize(self):
 
 
             # USER SAVED MUSIC & FOLLOW ARTIST MODEL
-class SavedMusic(db.Model):
-    __tablename__ = "saved_music"
+class SavedSong(db.Model):
+    __tablename__ = "saved_song"
 
     id = db.Column(db.Integer, primary_key=True)
 
     # Relationships
     user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
-    music_id = db.Column(db.Integer, db.ForeignKey("music.id"))
+    song_id = db.Column(db.Integer, db.ForeignKey("song.id"))
 
     def __repr__(self):
-        return f'<Saved_Music {self.music_id}>'
+        return f'<Saved_Song {self.song_id}>'
 
     def serialize(self):
         return {
             "id": self.id,
             "user_id": self.user_id,
-            "music_id": self.music_id
+            "song_id": self.song_id
         }
     
 
@@ -192,7 +192,7 @@ class FollowArtist(db.Model):
     artist_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), primary_key=True)
 
     def __repr__(self):
-        return f'<Follow_Artist user_id={self.user_id}, artist_id={self.artist_id}, is_active={self.is_active}>'
+        return f'<FollowArtist user_id={self.user_id}, artist_id={self.artist_id}, is_active={self.is_active}>'
 
     def serialize(self):
         return {
diff --git a/src/api/routes.py b/src/api/routes.py
index 19a3d3bcd0..d0e38d0940 100644
--- a/src/api/routes.py
+++ b/src/api/routes.py
@@ -2,12 +2,12 @@
 This module takes care of starting the API Server, Loading the DB and Adding the endpoints
 """
 from flask import Flask, request, jsonify, url_for, Blueprint
-from api.models import db, User, Genre, ArtistProfile, Photo, Video, Music, SavedMusic, FollowArtist
+from api.models import db, User, Genre, ArtistProfile, Photo, Video, Song, SavedSong, FollowArtist
 from api.utils import generate_sitemap, APIException
 from flask_cors import CORS
 import os
 
-from flask_jwt_extended import create_access_token, current_user, jwt_required
+from flask_jwt_extended import create_access_token, current_user, jwt_required, get_jwt_identity
 
 
 import requests
@@ -188,7 +188,7 @@ def get_artist_songs(artist_id):
         return jsonify({"msg": "Artista no encontrado"}), 404
 
     # Obtén la musica para este artista
-    songs = Music.query.filter_by(artist_id=artist_id).all()
+    songs = Song.query.filter_by(artist_id=artist_id).all()
     serialized_songs = [s.serialize() for s in songs]
     return jsonify(serialized_songs), 200
 
@@ -210,7 +210,7 @@ def create_artist_song(artist_id):
         return jsonify({"msg": "media_url is required"}), 400
 
     # Creamos la musica
-    new_song = Music(
+    new_song = Song(
         title=title,
         media_url=media_url,
         artist_id=artist_id
@@ -227,10 +227,92 @@ def delete_artist_song(artist_id, song_id):
     if not artist:
         return jsonify({"msg": "Artista no encontrado"}), 404
 
-    song = Music.query.filter_by(id=song_id, artist_id=artist_id).first()
+    song = Song.query.filter_by(id=song_id, artist_id=artist_id).first()
     if not song:
         return jsonify({"msg": "Cancion no encontrada"}), 404
 
     db.session.delete(song)
     db.session.commit()
-    return jsonify({"msg": "Cancion eliminada con éxito"}), 200
\ No newline at end of file
+    return jsonify({"msg": "Cancion eliminada con éxito"}), 200
+
+
+
+# GET USER FAVOURITE SONGS AND ARTISTS
+@api.route('/user/profile/<int:id>', methods=['GET'])
+def handle_user_favourites(id):
+    # Find the user by id
+    user = User.query.get(id)
+
+    if not user:
+        return jsonify({"ERROR": "Usuario no encontrado"}), 404
+     
+    return jsonify({
+        "saved_songs": [fav.serialize() for fav in user.saved_songs] if user.saved_songs else "No hay canciones guardadas",
+        "followed_artists": [fav.serialize() for fav in user.followed_artists] if user.followed_artists else "No tienes artistas guardados"
+    }), 200
+
+
+
+# POST & DELETE FOR USER FAVOURITE SONGS
+@api.route('/user/profile/<int:id>/favorite/songs/<int:song_id>', methods=['POST', 'DELETE'])
+def handle_favourite_songs(song_id, id):
+    # Find the user by id
+    user = User.query.get(id)
+
+    if not user:
+        return jsonify({"ERROR": "Usuario no encontrado"}), 404
+    
+    # Check if the song is already liked/favourited by the user
+    existing_favourite_song = SavedSong.query.filter_by(user_id=id, song_id=song_id).first()
+
+    # POST
+    if request.method == 'POST':
+        if existing_favourite_song:
+            return jsonify({"msg": "La canción ya está en favoritos"}), 400
+        
+        new_favourite_song = SavedSong(user_id=id, song_id=song_id)
+        db.session.add(new_favourite_song)
+        db.session.commit()
+        return jsonify({"msg": "Canción añadida a favoritos con éxito", "new_favourite_song": new_favourite_song.serialize()}), 200
+
+    # DELETE
+    if request.method == 'DELETE':
+        if not existing_favourite_song:
+            return jsonify({"msg": "La canción no está en favoritos"}), 400
+
+        db.session.delete(existing_favourite_song)
+        db.session.commit()
+        return jsonify({"msg": "Canción eliminada de favoritos con éxito"}), 200
+
+
+
+# POST & DELETE FOR USER FOLLOWED ARTISTS
+@api.route('/user/profile/<int:id>/favorite/aritsts/<int:artist_id>', methods=['POST', 'DELETE'])
+def handle_followed_artists(artist_id, id):
+    # Find the user by id
+    user = User.query.get(id)
+
+    if not user:
+        return jsonify({"ERROR": "Usuario no encontrado"}), 404
+
+    # Check if the artist is already followed by the user
+    existing_followed_artist = FollowArtist.query.filter_by(user_id=id, artist_id=artist_id).first()
+
+    # POST
+    if request.method == 'POST':
+        if existing_followed_artist:
+            return jsonify({"msg": "Ya sigues a este artista"}), 400
+        
+        new_followed_artist = FollowArtist(user_id=id, artist_id=artist_id)
+        db.session.add(new_followed_artist)
+        db.session.commit()
+        return jsonify({"msg": "Artista seguido con éxito", "new_followed_artist": new_followed_artist.serialize()}), 200
+
+    # DELETE
+    if request.method == 'DELETE':
+        if not existing_followed_artist:
+            return jsonify({"msg": "No sigues a este artista"}), 400
+
+        db.session.delete(existing_followed_artist)
+        db.session.commit()
+        return jsonify({"msg": "Artista dejado de seguir con éxito"}), 200

From d10e9c7818b5e301e47184ad1f6172e7e04edd76 Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Mon, 10 Mar 2025 15:32:53 +0000
Subject: [PATCH 23/25] comentario commit

---
 Pipfile                                      |   3 +-
 Pipfile.lock                                 |  16 +-
 src/api/admin.py                             |   8 +-
 src/api/models.py                            | 106 +++--
 src/api/routes.py                            |  26 +-
 src/app.py                                   |   4 +-
 src/front/js/layout.js                       |  12 +-
 src/front/js/pages/{genre.js => HomeUser.js} |   2 +-
 src/front/js/pages/{home.js => genre2.js}    |   2 +-
 src/front/js/pages/login.js                  | 433 ++++++++++---------
 10 files changed, 327 insertions(+), 285 deletions(-)
 rename src/front/js/pages/{genre.js => HomeUser.js} (98%)
 rename src/front/js/pages/{home.js => genre2.js} (95%)

diff --git a/Pipfile b/Pipfile
index 6429bd1f18..9a459ca534 100644
--- a/Pipfile
+++ b/Pipfile
@@ -20,10 +20,9 @@ flask-admin = "*"
 typing-extensions = "*"
 wtforms = "==3.1.2"
 flask-extended = "*"
+requests = "*"
 flask-jwt-extended = "*"
 pyjwt = "==2.9.0"
-requests = "*"
-
 
 [requires]
 python_version = "3.10"
diff --git a/Pipfile.lock b/Pipfile.lock
index 35fcf34ad2..86740c5d72 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,11 +1,7 @@
 {
     "_meta": {
         "hash": {
-
-            "sha256": "df7144212363e2fb107242f0448476de13fa283a57b574ff560e2a499fbc4049"
-
-            "sha256": "565f98e9600186b666ea99818452df31f2af6834fd198eaf1fcc557fed5d866b"
-
+            "sha256": "f330cd23b0270ece3f391c1a9745b0587e3adc87478d87f3d8a1e118c43e72c3"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -178,7 +174,6 @@
             "hashes": [
                 "sha256:6ccb38d16d6b72bbc156c1c3f192bc435bfcc3c2bc864b2df1eb9b2d97b2403c",
                 "sha256:fa5cb364ead54bbf401a26dbf03030c6b18fb2fcaf70408096a572b409586b0c"
-
             ],
             "index": "pypi",
             "version": "==5.0.1"
@@ -190,9 +185,6 @@
             ],
             "index": "pypi",
             "version": "==0.2"
-            ],
-            "index": "pypi",
-            "version": "==5.0.1"
         },
         "flask-jwt-extended": {
             "hashes": [
@@ -331,11 +323,11 @@
         },
         "jinja2": {
             "hashes": [
-                "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb",
-                "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"
+                "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d",
+                "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==3.1.5"
+            "version": "==3.1.6"
         },
         "mako": {
             "hashes": [
diff --git a/src/api/admin.py b/src/api/admin.py
index 1979841fc9..58410e318a 100644
--- a/src/api/admin.py
+++ b/src/api/admin.py
@@ -1,7 +1,7 @@
   
 import os
 from flask_admin import Admin
-from .models import db, User, Genre
+from .models import db, User, Genre, ArtistProfile,Photo,Video,Music,SavedMusic,FollowArtist
 from flask_admin.contrib.sqla import ModelView
 
 def setup_admin(app):
@@ -13,6 +13,12 @@ def setup_admin(app):
     # Add your models here, for example this is how we add a the User model to the admin
     admin.add_view(ModelView(User, db.session))
     admin.add_view(ModelView(Genre, db.session))
+    admin.add_view(ModelView(Photo, db.session))
+    admin.add_view(ModelView(Video, db.session))
+    admin.add_view(ModelView(Music, db.session))
+    admin.add_view(ModelView(SavedMusic, db.session))
+    admin.add_view(ModelView(FollowArtist, db.session))
+    admin.add_view(ModelView(ArtistProfile, db.session))
 
     # You can duplicate that line to add mew models
     # admin.add_view(ModelView(YourModelName, db.session))
\ No newline at end of file
diff --git a/src/api/models.py b/src/api/models.py
index 9e53b9a66b..9522a847b4 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -1,35 +1,32 @@
 from flask_sqlalchemy import SQLAlchemy
-from werkzeug.security import generate_password_hash, check_password_hash
 
+from werkzeug.security import generate_password_hash, check_password_hash
 
 db = SQLAlchemy()
 
-        #  USER REGISTER AND PROFILE MODEL
+# USER REGISTER AND PROFILE MODEL
 class User(db.Model):
     __tablename__ = "user"
 
     id = db.Column(db.Integer, primary_key=True)
-
     fullName = db.Column(db.String(120), unique=True, nullable=True)
     username = db.Column(db.String(120), unique=True, nullable=True)
     address = db.Column(db.String(120), unique=True, nullable=False)
-
     email = db.Column(db.String(120), unique=True, nullable=False)
     password_hash = db.Column(db.String(512), unique=False, nullable=False)
-
-    is_artist = db.Column(db.Boolean, default=False) # Check if account is artist
+    is_artist = db.Column(db.Boolean, default=False)  # Check if account is artist
     is_active = db.Column(db.Boolean(), default=True)
     profile_photo = db.Column(db.String(255), nullable=True)  # Profile photo URL
 
-    #  Relationships
-    followed_artists = db.relationship('Follow_Artist', backref='follow_artist')
-    saved_music = db.relationship('Saved_Music', backref='user')
+    # Relationships
+    followed_artists = db.relationship('FollowArtist', backref='follow_artist')
+    saved_music = db.relationship('SavedMusic', backref='user')
 
     def __repr__(self):
         return f'<User {self.username}>'
 
-    def artist(is_artist):
-        if is_artist:
+    def artist(self):
+        if self.is_artist:
             return "Si"
         else:
             return "No"
@@ -45,41 +42,41 @@ def serialize(self):
             "profile_photo": self.profile_photo,
         }
 
-def set_password(self, password):
-    self.password_hash = generate_password_hash(password)
+    def set_password(self, password):
+        self.password_hash = generate_password_hash(password)
 
-def check_password(self,password):
-    return check_password_hash(self.password_hash,password)
+    def check_password(self,password):
+        return check_password_hash(self.password_hash,password)
 
 
-        # ARTIST PROFILE MODEL
-class Artist_Profile(db.Model):
+# ARTIST PROFILE MODEL
+class ArtistProfile(db.Model):
     __tablename__ = "artist_profile"
 
     id = db.Column(db.Integer, primary_key=True)
     bio = db.Column(db.Text, nullable=True)
 
     # Relationships
-    artist_id = db.Column(db.Integer, db.ForeignKey('users.id'), unique=True, nullable=False)
+    artist_id = db.Column(db.Integer, db.ForeignKey('user.id'), unique=True, nullable=False)
 
-    artist_photos = db.relationship("Photo", backref="artist")
-    artist_videos = db.relationship("Video", backref="artist")
-    artist_music = db.relationship("Music", backref="artist")
+    artist_photos = db.relationship("Photo", backref="artist_profile")
+    artist_videos = db.relationship("Video", backref="artist_profile")
+    artist_music = db.relationship("Music", backref="artist_profile")
 
     def __repr__(self):
-        return f'<Artist_Profile {self.id}>'
+        return f'<ArtistProfile {self.id}>'
 
     def serialize(self):
         return {
             "id": self.id,
             "artist_id": self.artist_id,
             "bio": self.bio,
-            "artist_photos": self.artist_photos,
-            "artist_videos": self.artist_videos,
-            "artist_music": self.artist_music
+            "artist_photos": [photo.serialize() for photo in self.artist_photos],
+            "artist_videos": [video.serialize() for video in self.artist_videos],
+            "artist_music": [music.serialize() for music in self.artist_music]
         }
-    
-                # ARTIST PHOTO MODEL
+
+# ARTIST PHOTO MODEL
 class Photo(db.Model):
     __tablename__ = "photo"
 
@@ -88,7 +85,7 @@ class Photo(db.Model):
     media_url = db.Column(db.Text, nullable=False)  # Cloudinary URL
 
     # Relationships
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+    artist_profile_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), nullable=False)
 
     def __repr__(self):
         return f'<Photo {self.title}>'
@@ -101,7 +98,7 @@ def serialize(self):
         }
 
 
-                # ARTIST VIDEO MODEL
+# ARTIST VIDEO MODEL
 class Video(db.Model):
     __tablename__ = "video"
 
@@ -111,7 +108,7 @@ class Video(db.Model):
     duration = db.Column(db.Integer, nullable=False)
 
     # Relationships
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+    artist_profile_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), nullable=False)
 
     def __repr__(self):
         return f'<Video {self.title}>'
@@ -124,22 +121,8 @@ def serialize(self):
             "duration": self.duration,
         }
 
-        # GENRES MODEL TO LOAD GENRES
-class Genre(db.Model):
-  
-    id = db.Column(db.Integer, primary_key=True)
-    name = db.Column(db.String(250), unique=True, nullable=False)
 
-    def __repr__(self):
-        return f'<Genre {self.name}>'
-      
-    def serialize(self):
-        return {
-          "id": self.id,
-          "name": self.name
-        }
-      
-                # ARTIST MUSIC MODEL
+# ARTIST MUSIC MODEL
 class Music(db.Model):
     __tablename__ = "music"
 
@@ -149,7 +132,7 @@ class Music(db.Model):
     duration = db.Column(db.Integer, nullable=False)
 
     # Relationships
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), nullable=False)
+    artist_profile_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), nullable=False)
 
     def __repr__(self):
         return f'<Music {self.title}>'
@@ -163,8 +146,8 @@ def serialize(self):
         }
 
 
-            # USER SAVED MUSIC & FOLLOW ARTIST MODEL
-class Saved_Music(db.Model):
+# USER SAVED MUSIC & FOLLOW ARTIST MODEL
+class SavedMusic(db.Model):
     __tablename__ = "saved_music"
 
     id = db.Column(db.Integer, primary_key=True)
@@ -174,7 +157,7 @@ class Saved_Music(db.Model):
     music_id = db.Column(db.Integer, db.ForeignKey("music.id"))
 
     def __repr__(self):
-        return f'<Saved_Music {self.music_id}>'
+        return f'<SavedMusic {self.music_id}>'
 
     def serialize(self):
         return {
@@ -182,20 +165,33 @@ def serialize(self):
             "user_id": self.user_id,
             "music_id": self.music_id
         }
-    
 
-                # FOLLOW ARTIST MODEL
-class Follow_Artist(db.Model):
+
+# FOLLOW ARTIST MODEL
+class FollowArtist(db.Model):
     __tablename__ = "follow_artist"
 
     user_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
-    artist_id = db.Column(db.Integer, db.ForeignKey("artist.id"), primary_key=True)
+    artist_profile_id = db.Column(db.Integer, db.ForeignKey("artist_profile.id"), primary_key=True)
 
     def __repr__(self):
-        return f'<Follow_Artist user_id={self.user_id}, artist_id={self.artist_id}, is_active={self.is_active}>'
+        return f'<Follow_Artist user_id={self.user_id}, artist_profile_id={self.artist_profile_id}>'
 
     def serialize(self):
         return {
             "user_id": self.user_id,
-            "artist_id": self.artist_id,
+            "artist_profile_id": self.artist_profile_id,
         }
+class Genre(db.Model):
+
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(250), unique=True, nullable=False)
+
+    def __repr__(self):
+        return f'<Genre {self.name}>'
+
+    def serialize(self):
+        return {
+          "id": self.id,
+          "name": self.name
+        }
\ No newline at end of file
diff --git a/src/api/routes.py b/src/api/routes.py
index 96046518c9..aad7dea1e4 100644
--- a/src/api/routes.py
+++ b/src/api/routes.py
@@ -49,6 +49,8 @@ def upload_image():
 
 
 
+
+
 # Creacion de usuario 
 @api.route('/register', methods=['POST'])
 def register():
@@ -57,6 +59,7 @@ def register():
     address = request.json.get('address', None)
     email = request.json.get('email', None)
     password = request.json.get('password', None)
+    is_artist = request.json.get(True,None)
 
     if not fullName or not username or not email or not password:
         return jsonify({"msg": "Missing required fields"}), 400
@@ -69,7 +72,7 @@ def register():
     if existing_user:
         return jsonify({"msg": "Username already exists"}), 400
 
-    user = User(fullName=fullName, username=username, address=address, email=email, is_artist=True, is_active=True)
+    user = User(fullName=fullName, username=username, address=address, email=email, is_artist=is_artist, is_active=True)
     user.set_password(password)
 
     db.session.add(user)
@@ -82,14 +85,27 @@ def generate_token():
     username = request.json.get("username", None)
     password = request.json.get("password", None)
 
+    # Buscar al usuario por el nombre de usuario
     user = User.query.filter_by(username=username).one_or_none()
 
+    # Verificar si el usuario existe y la contraseña es correcta
     if not user or not user.check_password(password):
-        return jsonify("Wrong username or password"), 401
+        return jsonify({"message": "Wrong username or password"}), 401
     
-    access_token = create_access_token(identity=user)  # Se pasa user.id
-    return jsonify(access_token=access_token)
-
+    # Crear el token de acceso
+    access_token = create_access_token(identity=user)
+
+    # Redirigir dependiendo de si es artista o no
+    if user.is_artist:
+        return jsonify({
+            "access_token": access_token,
+            "redirect_url": f"/user/{user.id}"
+        })
+    else:
+        return jsonify({
+            "access_token": access_token,
+            "redirect_url": "/homeuser"
+        })
 
 @api.route('/profile', methods=['GET'])
 @jwt_required()
diff --git a/src/app.py b/src/app.py
index 2ad028d6a2..2459f08a9e 100644
--- a/src/app.py
+++ b/src/app.py
@@ -20,7 +20,7 @@
 app = Flask(__name__)
 app.url_map.strict_slashes = False
 
-# database condiguration
+# database configuration
 db_url = os.getenv("DATABASE_URL")
 if db_url is not None:
     app.config['SQLALCHEMY_DATABASE_URI'] = db_url.replace(
@@ -32,6 +32,8 @@
 MIGRATE = Migrate(app, db, compare_type=True)
 db.init_app(app)
 
+
+
 # add the admin
 setup_admin(app)
 
diff --git a/src/front/js/layout.js b/src/front/js/layout.js
index f4abf9b78f..1b7dbc09d9 100755
--- a/src/front/js/layout.js
+++ b/src/front/js/layout.js
@@ -3,7 +3,7 @@ import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
 import ScrollToTop from "./component/scrollToTop";
 import { BackendURL } from "./component/backendURL";
 
-import { Home } from "./pages/home";
+import { Genre2 } from "./pages/genre2";
 import { Demo } from "./pages/demo";
 import { Single } from "./pages/single";
 import injectContext from "./store/appContext";
@@ -13,7 +13,7 @@ import { UserProfile } from "./pages/UserProfile"; // ✅ Nueva vista
 import { SavedSongs } from "./pages/SavedSongs"; // ✅ Nueva vista
 import { SavedArtists } from "./pages/SavedArtists"; // ✅ Nueva vista
 import ArtistProfile from "./pages/ArtistProfile";
-import { Genre } from "./pages/genre";
+import { HomeUser } from "./pages/HomeUser";
 import { UserData } from "./pages/UserData"
 import { ArtistData } from "./pages/ArtistData"
 import { Navbar } from "./component/navbar";
@@ -39,18 +39,18 @@ const Layout = () => {
 const LayoutContent = () => {
     const location = useLocation(); // Obtiene la ruta actual
 
-    const hideNavbarFooter = location.pathname === "/login"; // Solo oculta en /login
+    const hideNavbarFooter = location.pathname === "/"; // Solo oculta en /login
 
     return (
         <>
             {!hideNavbarFooter && <Navbar />}
 
             <Routes>
-                <Route element={<Home />} path="/" />
-                <Route element={<Login />} path="/login" />
+                <Route element={<Genre2 />} path="/genre2" />
+                <Route element={<Login />} path="/" />
                 <Route element={<Demo />} path="/demo" />
                 <Route element={<Single />} path="/single/:theid" />
-                <Route element={<Genre />} path="/genre" />
+                <Route element={<HomeUser />} path="/homeuser" />
                 <Route element={<UserProfile />} path="/userProfile" />  {/* ✅ nueva */}
                 <Route element={<SavedSongs />} path="/savedSongs" />  {/* ✅ nueva */}
                 <Route element={<SavedArtists />} path="/savedArtists" />  {/* ✅ nueva */}
diff --git a/src/front/js/pages/genre.js b/src/front/js/pages/HomeUser.js
similarity index 98%
rename from src/front/js/pages/genre.js
rename to src/front/js/pages/HomeUser.js
index 6a53e12cc2..cc7dae013f 100644
--- a/src/front/js/pages/genre.js
+++ b/src/front/js/pages/HomeUser.js
@@ -3,7 +3,7 @@ import { useContext } from 'react';
 import { Context } from "../store/appContext";
 import "../../styles/genre.css"
 
-export const Genre = () => {
+export const HomeUser = () => {
 
     const { store, actions } = useContext(Context);
 
diff --git a/src/front/js/pages/home.js b/src/front/js/pages/genre2.js
similarity index 95%
rename from src/front/js/pages/home.js
rename to src/front/js/pages/genre2.js
index 7b0be46a1e..3ec417545f 100755
--- a/src/front/js/pages/home.js
+++ b/src/front/js/pages/genre2.js
@@ -3,7 +3,7 @@ import { Context } from "../store/appContext";
 import rigoImageUrl from "../../img/rigo-baby.jpg";
 import "../../styles/home.css";
 
-export const Home = () => {
+export const Genre2 = () => {
 	const { store, actions } = useContext(Context);
 
 	return (
diff --git a/src/front/js/pages/login.js b/src/front/js/pages/login.js
index 043755db23..aa0c7a7a25 100644
--- a/src/front/js/pages/login.js
+++ b/src/front/js/pages/login.js
@@ -10,89 +10,110 @@ export const Login = () => {
 
   //Estado para almacenar datos del formulario de registro
 
-  const[formulario, setFormulario] = useState({
-    fullName:"",
-    username:"",
-    email:"",
-    address:"",
-    password:"",
-    confirmPassword:"",
+  const [formulario, setFormulario] = useState({
+    fullName: "",
+    username: "",
+    email: "",
+    address: "",
+    password: "",
+    confirmPassword: "",
+    isArtist: false,
   });
 
   // Estados para manejar el login
   const [loginData, setLoginData] = useState({
-    username:"",
-    password:"",
+    username: "",
+    password: "",
   });
 
   // Manejar los cambios en los inputs del registro
   const handleChange = (e) => {
-    setFormulario({...formulario, [e.target.name]: e.target.value});
+    if (e.target.type === "checkbox") {
+      setFormulario({
+        ...formulario,
+        [e.target.name]: e.target.checked, // Para checkbox, usamos checked
+      });
+    } else {
+      setFormulario({ ...formulario, [e.target.name]: e.target.value });
+    }
   };
 
   // Manejar cambios en  los inpusts del login
   const handleLoginChange = (e) => {
-    console.log("cambir campos: ", e.target.name, "Nuevo valor:", e.target.value);
-    setLoginData({...loginData, [e.target.name]:e.target.value});
+    console.log("cambiar campos: ", e.target.name, "Nuevo valor:", e.target.value);
+    setLoginData({ ...loginData, [e.target.name]: e.target.value });
   };
 
-  // Enviar formulario de registro
-  const handleRegister = async (e) =>{
+  const handleRegister = async (e) => {
     e.preventDefault();
-    
-    if (formulario.password !== formulario.confirmPassword){
+
+    if (formulario.password !== formulario.confirmPassword) {
       alert("Las contraseñas no coinciden");
       return;
     }
-    
-    console.log("Datos del formulario de registro:", formulario); // Verifica que los datos sean correctos antes de enviarlos
 
-    try{
-      const response = await fetch("https://fluffy-chainsaw-v6qq999gg9xwfx99v-3001.app.github.dev/api/register",{
-        method:"POST",
-        headers:{"Content-type":"application/json"},
-        body:JSON.stringify(formulario),
+    // Aseguramos que isArtist sea false si no está marcado
+    const dataToSend = {
+      ...formulario,
+      isArtist: formulario.isArtist || false,  // Si no está marcado, será false
+    };
+
+    console.log("Datos del formulario de registro:", dataToSend); // Verifica que los datos sean correctos antes de enviarlos
+
+    try {
+      const response = await fetch("https://ideal-space-bassoon-jjqqvvv4q5g4hqpjr-3001.app.github.dev/api/register", {
+        method: "POST",
+        headers: { "Content-type": "application/json" },
+        body: JSON.stringify(dataToSend),
       });
 
       const data = await response.json();
 
-      if(response.ok){
-        alert("Usuario registrado con exito");
+      if (response.ok) {
+        alert("Usuario registrado con éxito");
         setShowRegister(false);
         setShowLogin(true);
-      }else{
-        alert(data.message || "Error al registrar usuario")
+      } else {
+        alert(data.message || "Error al registrar usuario");
       }
-    } catch(error){
-      alert("Error en el servidor")
+    } catch (error) {
+      alert("Error en el servidor");
     }
   };
 
-  // Enviar formulario de inicio de sesion
-  const handleLogin = async (e) =>{
+  // Enviar formulario de inicio de sesión
+  const handleLogin = async (e) => {
     e.preventDefault();
-
-    try{
-      const response = await fetch("https://fluffy-chainsaw-v6qq999gg9xwfx99v-3001.app.github.dev/login", {
-        method:"POST",
-        headers:{"Content-Type":"application/json"},
-        body: JSON.stringify(loginData)
+    try {
+      const response = await fetch("https://ideal-space-bassoon-jjqqvvv4q5g4hqpjr-3001.app.github.dev/api/login", {
+        method: "POST",
+        headers: { "Content-Type": "application/json" },
+        body: JSON.stringify(loginData),
       });
 
+      if (!response.ok) {
+        const errorData = await response.json();
+        throw new Error(errorData.message || "Error en el inicio de sesión");
+      }
+
       const data = await response.json();
+      console.log("Respuesta del servidor:", data);
 
-      if(response.ok){
-        alert("Inicio de sesion correcto");
-        localStorage.setItem("Token", data.token); // Guarda el token en local
-        localStorage.setItem("user", JSON.stringify(data.user)) // guarda los datos del usuario
-        // aqui puedes redirir a otra pagina
-      } else{
-        alert(data.message || "Error al iniciar sesion")
+      // Redirigir a la URL proporcionada en la respuesta del servidor
+      if (data.redirect_url) {
+        window.location.href = data.redirect_url;
       }
-    }catch (error){
-      alert("Error en el servidor")
+
+      // Guardar token y datos del usuario
+      localStorage.setItem("Token", data.access_token);
+      localStorage.setItem("user", JSON.stringify(data.user));
+
+    } catch (error) {
+      console.error("Error al hacer fetch:", error);
+      alert(error.message || "Error en el servidor");
     }
-  }
+  };
+
 
   return (
     <div
@@ -139,170 +160,180 @@ export const Login = () => {
         {/* Formulario de inicio de sesión */}
         {showLogin && !showForgoten && (
           <form onSubmit={handleLogin}>
-          <h2 className="text-center mb-4">Iniciar sesión</h2>
-          <div className="mb-3">
-            <input
-              type="text"
-              className="form-control form-control-lg"
-              placeholder="Nombre de usuario"
-              name = "username"
-              value={loginData.username}
-              onChange={handleLoginChange}
-              required
-            />
-          </div>
-          <div className="mb-3">
-            <input
-              type="password"
-              className="form-control form-control-lg"
-              placeholder="Contraseña"
-              name = "password"
-              value={loginData.password}
-              onChange={handleLoginChange}
-              required
-            />
-          </div>
-          <button type="submit" className="btn btn-danger w-100 py-2">
-            Ingresar
-          </button>
-          <div className="text-center mt-2">
-            <a href="#" className="text-decoration-none" onClick={() =>
-              setShowForgoten(true)
-            }>¿He olvidado mi contraseña?</a>
-            <button
-              type="button"
-              className="btn btn-link w-100 mt-2"
-              onClick={() => {
-                setShowForgoten(false);
-                setShowLogin(false);
-                setShowRegister(false)
-              }}
-            >
-              Volver
+            <h2 className="text-center mb-4">Iniciar sesión</h2>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Nombre de usuario"
+                name="username"
+                value={loginData.username}
+                onChange={handleLoginChange}
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="password"
+                className="form-control form-control-lg"
+                placeholder="Contraseña"
+                name="password"
+                value={loginData.password}
+                onChange={handleLoginChange}
+                required
+              />
+            </div>
+            <button type="submit" className="btn btn-danger w-100 py-2">
+              Ingresar
             </button>
-          </div>
-        </form >
+            <div className="text-center mt-2">
+              <a href="#" className="text-decoration-none" onClick={() =>
+                setShowForgoten(true)
+              }>¿He olvidado mi contraseña?</a>
+              <button
+                type="button"
+                className="btn btn-link w-100 mt-2"
+                onClick={() => {
+                  setShowForgoten(false);
+                  setShowLogin(false);
+                  setShowRegister(false)
+                }}
+              >
+                Volver
+              </button>
+            </div>
+          </form >
         )}
 
         {/* Formulario de registro */}
         {showRegister && (
           <form onSubmit={handleRegister}>
-          <h2 className="text-center mb-4">Registro</h2>
-          <div className="mb-3">
-            <input
-              type="text"
-              className="form-control form-control-lg"
-              placeholder="Nombre y apellidos"
-              name="fullName"
-              value={formulario.fullName}
-              onChange={handleChange}
-              required
-            />
-          </div>
-          <div className="mb-3">
-            <input
-              type="text"
-              className="form-control form-control-lg"
-              placeholder="Nombre de usuario"
-              name="username"
-              value={formulario.username}
-              onChange={handleChange}
-              required
-            />
-          </div>
-          <div className="mb-3">
-            <input
-              type="email"
-              className="form-control form-control-lg"
-              placeholder="Correo electrónico"
-              name = "email"
-              value={formulario.email}
-              onChange={handleChange}
-              required
-            />
-          </div>
-          <div className="mb-3">
-            <input
-              type="text"
-              className="form-control form-control-lg"
-              placeholder="Dirección"
-              name = "address"
-              value={formulario.address}
-              onChange={handleChange}
-              required
-            />
-          </div>
-          <div className="mb-3">
-            <input
-              type="password"
-              className="form-control form-control-lg"
-              placeholder="Contraseña"
-              name = "password"
-              value={formulario.password}
-              onChange={handleChange}
-              required
-            />
-          </div>
-          <div className="mb-3">
-            <input
-              type="password"
-              className="form-control form-control-lg"
-              placeholder="Confirmar contraseña"
-              name = "confirmPassword"
-              value={formulario.confirmPassword}
-              onChange={handleChange}
-              required
-            />
-          </div>
-          <div className="mb-3">
-            <label className="form-label">Subir foto de perfil</label>
-            <input type="file" className="form-control form-control-lg" />
-          </div>
-          <button type="submit" className="btn btn-success w-100 py-2">
-            Registrarse
-          </button>
-          <button
-            type="button"
-            className="btn btn-link w-100 mt-2"
-            onClick={() => setShowRegister(false)}
-          >
-            Volver
-          </button>
-        </form>
+            <h2 className="text-center mb-4">Registro</h2>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Nombre y apellidos"
+                name="fullName"
+                value={formulario.fullName}
+                onChange={handleChange}
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Nombre de usuario"
+                name="username"
+                value={formulario.username}
+                onChange={handleChange}
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="email"
+                className="form-control form-control-lg"
+                placeholder="Correo electrónico"
+                name="email"
+                value={formulario.email}
+                onChange={handleChange}
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Dirección"
+                name="address"
+                value={formulario.address}
+                onChange={handleChange}
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="password"
+                className="form-control form-control-lg"
+                placeholder="Contraseña"
+                name="password"
+                value={formulario.password}
+                onChange={handleChange}
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="password"
+                className="form-control form-control-lg"
+                placeholder="Confirmar contraseña"
+                name="confirmPassword"
+                value={formulario.confirmPassword}
+                onChange={handleChange}
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <label className="form-label me-2">¿Eres artista?</label>
+              <input
+                type="checkbox"
+                className="form-check-input"
+                name="isArtist"
+                checked={formulario.isArtist} // Se gestiona el estado de este checkbox
+                onChange={handleChange}
+              />
+            </div>
+            <div className="mb-3">
+              <label className="form-label">Subir foto de perfil</label>
+              <input type="file" className="form-control form-control-lg" />
+            </div>
+            <button type="submit" className="btn btn-success w-100 py-2">
+              Registrarse
+            </button>
+            <button
+              type="button"
+              className="btn btn-link w-100 mt-2"
+              onClick={() => setShowRegister(false)}
+            >
+              Volver
+            </button>
+          </form>
         )}
         {/* Formulario de recuperar contraseña*/}
         {showForgoten && (
           <form onSubmit={handleRegister}>
-          <h2 className="text-center mb-4">¿He olvidado mi contraseña?</h2>
-          <div className="mb-3">
-            <input
-              type="text"
-              className="form-control form-control-lg"
-              placeholder="Nomber de usuario"
-              required
-            />
-          </div>
-          <div className="mb-3">
-            <input
-              type="password"
-              className="form-control form-control-lg"
-              placeholder="Nueva contraseña"
-              required
-            />
-          </div>
-          <button
-            type="button"
-            className="btn btn-link w-100 mt-2"
-            onClick={() => {
-              setShowLogin(true);
-              setShowRegister(false);
-              setShowForgoten(false)
-            }}
-          >
-            Volver
-          </button>
-        </form>
-      )}
+            <h2 className="text-center mb-4">¿He olvidado mi contraseña?</h2>
+            <div className="mb-3">
+              <input
+                type="text"
+                className="form-control form-control-lg"
+                placeholder="Nomber de usuario"
+                required
+              />
+            </div>
+            <div className="mb-3">
+              <input
+                type="password"
+                className="form-control form-control-lg"
+                placeholder="Nueva contraseña"
+                required
+              />
+            </div>
+            <button
+              type="button"
+              className="btn btn-link w-100 mt-2"
+              onClick={() => {
+                setShowLogin(true);
+                setShowRegister(false);
+                setShowForgoten(false)
+              }}
+            >
+              Volver
+            </button>
+          </form>
+        )}
 
 
       </div>

From a51f2a8979c85ee3cfba7ab5789ea7ea2b23269b Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Mon, 10 Mar 2025 16:35:04 +0000
Subject: [PATCH 24/25] logindefinitivo

---
 src/front/js/component/navbar.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/front/js/component/navbar.js b/src/front/js/component/navbar.js
index 8837c3fcdc..addaf673b1 100755
--- a/src/front/js/component/navbar.js
+++ b/src/front/js/component/navbar.js
@@ -23,7 +23,8 @@ export const Navbar = () => {
                 {/* Menú desplegable */}
                 <div className={`dropdown-menu ${menuOpen ? "show" : ""}`}>
                     <Link to="/userProfile" className="dropdown-item" onClick={() => setMenuOpen(false)}>Perfil</Link>
-                    <Link to="/logout" className="dropdown-item" onClick={() => setMenuOpen(false)}>Logout</Link>
+                    <Link to="/userdata" className="dropdown-item" onClick={() => setMenuOpen(false)}>Datos</Link>
+                    <Link to="/" className="dropdown-item" onClick={() => setMenuOpen(false)}>Logout</Link>
                 </div>
                 </div>
             </div>

From 45fd4ded7ce5f2f4311cfa5fbf77f163acd8c2a7 Mon Sep 17 00:00:00 2001
From: Oscar Parra <oscarparrapalomino@gmail.com>
Date: Mon, 10 Mar 2025 18:31:08 +0000
Subject: [PATCH 25/25] espero que vaya

---
 src/api/admin.py  | 6 +++---
 src/api/models.py | 1 -
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/api/admin.py b/src/api/admin.py
index 58410e318a..21e5630954 100644
--- a/src/api/admin.py
+++ b/src/api/admin.py
@@ -1,7 +1,7 @@
   
 import os
 from flask_admin import Admin
-from .models import db, User, Genre, ArtistProfile,Photo,Video,Music,SavedMusic,FollowArtist
+from .models import db, User, Genre, ArtistProfile,Photo,Video,Song,SavedSong,FollowArtist
 from flask_admin.contrib.sqla import ModelView
 
 def setup_admin(app):
@@ -15,8 +15,8 @@ def setup_admin(app):
     admin.add_view(ModelView(Genre, db.session))
     admin.add_view(ModelView(Photo, db.session))
     admin.add_view(ModelView(Video, db.session))
-    admin.add_view(ModelView(Music, db.session))
-    admin.add_view(ModelView(SavedMusic, db.session))
+    admin.add_view(ModelView(Song, db.session))
+    admin.add_view(ModelView(SavedSong, db.session))
     admin.add_view(ModelView(FollowArtist, db.session))
     admin.add_view(ModelView(ArtistProfile, db.session))
 
diff --git a/src/api/models.py b/src/api/models.py
index 9c064d348c..36f4132e69 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -61,7 +61,6 @@ class ArtistProfile(db.Model):
 
     artist_photos = db.relationship("Photo", backref="artist_profile")
     artist_videos = db.relationship("Video", backref="artist_profile")
-    artist_music = db.relationship("Music", backref="artist_profile")
     artist_songs = db.relationship("Song", backref="artist_profile")
 
     def __repr__(self):