diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 000000000..092ddb648 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,529 @@ +{ + "_meta": { + "hash": { + "sha256": "704b8f6af20333a80c9e4f392f761f1cde64b113421da24aa3967b77473f7373" + }, + "pipfile-spec": 6, + "requires": { + "python_full_version": "3.8.13" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "alembic": { + "hashes": [ + "sha256:1ff0ae32975f4fd96028c39ed9bb3c867fe3af956bd7bb37343b54c9fe7445ef", + "sha256:6b8733129a6224a9a711e17c99b08462dbf7cc9670ba8f2e2ae9af860ceb1953" + ], + "markers": "python_version >= '3.8'", + "version": "==1.13.2" + }, + "aniso8601": { + "hashes": [ + "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f", + "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973" + ], + "version": "==9.0.1" + }, + "asttokens": { + "hashes": [ + "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", + "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0" + ], + "version": "==2.4.1" + }, + "backcall": { + "hashes": [ + "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e", + "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255" + ], + "version": "==0.2.0" + }, + "click": { + "hashes": [ + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.7" + }, + "decorator": { + "hashes": [ + "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", + "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" + ], + "markers": "python_version > '3.6'", + "version": "==5.1.1" + }, + "executing": { + "hashes": [ + "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147", + "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc" + ], + "markers": "python_version >= '3.5'", + "version": "==2.0.1" + }, + "faker": { + "hashes": [ + "sha256:0f60978314973de02c00474c2ae899785a42b2cf4f41b7987e93c132a2b8a4a9", + "sha256:886ee28219be96949cd21ecc96c4c742ee1680e77f687b095202c8def1a08f06" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==26.0.0" + }, + "flask": { + "hashes": [ + "sha256:58107ed83443e86067e41eff4631b058178191a355886f8e479e347fa1285fdf", + "sha256:edee9b0a7ff26621bd5a8c10ff484ae28737a2410d99b0bb9a6850c7fb977aa0" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==2.2.5" + }, + "flask-cors": { + "hashes": [ + "sha256:eeb69b342142fdbf4766ad99357a7f3876a2ceb77689dc10ff912aac06c389e4", + "sha256:f2a704e4458665580c074b714c4627dd5a306b333deb9074d0b1794dfa2fb677" + ], + "index": "pypi", + "version": "==4.0.1" + }, + "flask-migrate": { + "hashes": [ + "sha256:5c532be17e7b43a223b7500d620edae33795df27c75811ddf32560f7d48ec617", + "sha256:dff7dd25113c210b069af280ea713b883f3840c1e3455274745d7355778c8622" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==4.0.7" + }, + "flask-restful": { + "hashes": [ + "sha256:1cf93c535172f112e080b0d4503a8d15f93a48c88bdd36dd87269bdaf405051b", + "sha256:fe4af2ef0027df8f9b4f797aba20c5566801b6ade995ac63b588abf1a59cec37" + ], + "index": "pypi", + "version": "==0.3.10" + }, + "flask-sqlalchemy": { + "hashes": [ + "sha256:2764335f3c9d7ebdc9ed6044afaf98aae9fa50d7a074cef55dde307ec95903ec", + "sha256:add5750b2f9cd10512995261ee2aa23fab85bd5626061aa3c564b33bb4aa780a" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==3.0.3" + }, + "greenlet": { + "hashes": [ + "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67", + "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6", + "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257", + "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4", + "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676", + "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61", + "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc", + "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca", + "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7", + "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728", + "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305", + "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6", + "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379", + "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414", + "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04", + "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a", + "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf", + "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491", + "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559", + "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e", + "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274", + "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb", + "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b", + "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9", + "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b", + "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be", + "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506", + "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405", + "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113", + "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f", + "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5", + "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230", + "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d", + "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f", + "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a", + "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e", + "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61", + "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6", + "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d", + "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71", + "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22", + "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2", + "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3", + "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067", + "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc", + "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881", + "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3", + "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e", + "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac", + "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53", + "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0", + "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b", + "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83", + "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41", + "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c", + "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf", + "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da", + "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33" + ], + "markers": "python_version < '3.13' 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.0.3" + }, + "importlib-metadata": { + "hashes": [ + "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f", + "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812" + ], + "markers": "python_version < '3.10'", + "version": "==8.0.0" + }, + "importlib-resources": { + "hashes": [ + "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c", + "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145" + ], + "markers": "python_version < '3.9'", + "version": "==6.4.0" + }, + "ipdb": { + "hashes": [ + "sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5" + ], + "index": "pypi", + "markers": "python_version >= '2.7'", + "version": "==0.13.9" + }, + "ipython": { + "hashes": [ + "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363", + "sha256:b0340d46a933d27c657b211a329d0be23793c36595acf9e6ef4164bc01a1804c" + ], + "markers": "python_version > '3.6'", + "version": "==8.12.3" + }, + "itsdangerous": { + "hashes": [ + "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", + "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173" + ], + "markers": "python_version >= '3.8'", + "version": "==2.2.0" + }, + "jedi": { + "hashes": [ + "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd", + "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0" + ], + "markers": "python_version >= '3.6'", + "version": "==0.19.1" + }, + "jinja2": { + "hashes": [ + "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", + "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.4" + }, + "mako": { + "hashes": [ + "sha256:260f1dbc3a519453a9c856dedfe4beb4e50bd5a26d96386cb6c80856556bb91a", + "sha256:48dbc20568c1d276a2698b36d968fa76161bf127194907ea6fc594fa81f943bc" + ], + "markers": "python_version >= '3.8'", + "version": "==1.3.5" + }, + "markupsafe": { + "hashes": [ + "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", + "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", + "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", + "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", + "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", + "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", + "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", + "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df", + "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", + "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", + "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", + "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", + "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", + "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371", + "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2", + "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", + "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52", + "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", + "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", + "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", + "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", + "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", + "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", + "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", + "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", + "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", + "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", + "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", + "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", + "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9", + "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", + "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", + "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", + "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", + "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", + "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", + "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a", + "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", + "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", + "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", + "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", + "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", + "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", + "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", + "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", + "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f", + "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50", + "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", + "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", + "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", + "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", + "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", + "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", + "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", + "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf", + "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", + "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", + "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", + "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", + "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68" + ], + "markers": "python_version >= '3.7'", + "version": "==2.1.5" + }, + "matplotlib-inline": { + "hashes": [ + "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", + "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca" + ], + "markers": "python_version >= '3.8'", + "version": "==0.1.7" + }, + "parso": { + "hashes": [ + "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", + "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d" + ], + "markers": "python_version >= '3.6'", + "version": "==0.8.4" + }, + "pexpect": { + "hashes": [ + "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", + "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" + ], + "markers": "sys_platform != 'win32'", + "version": "==4.9.0" + }, + "pickleshare": { + "hashes": [ + "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca", + "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56" + ], + "version": "==0.7.5" + }, + "prompt-toolkit": { + "hashes": [ + "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10", + "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==3.0.47" + }, + "ptyprocess": { + "hashes": [ + "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", + "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" + ], + "version": "==0.7.0" + }, + "pure-eval": { + "hashes": [ + "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", + "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" + ], + "version": "==0.2.2" + }, + "pygments": { + "hashes": [ + "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", + "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a" + ], + "markers": "python_version >= '3.8'", + "version": "==2.18.0" + }, + "python-dateutil": { + "hashes": [ + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==2.9.0.post0" + }, + "pytz": { + "hashes": [ + "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812", + "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319" + ], + "version": "==2024.1" + }, + "setuptools": { + "hashes": [ + "sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05", + "sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1" + ], + "markers": "python_version >= '3.8'", + "version": "==70.2.0" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.16.0" + }, + "sqlalchemy": { + "hashes": [ + "sha256:0b0f658414ee4e4b8cbcd4a9bb0fd743c5eeb81fc858ca517217a8013d282c96", + "sha256:2196208432deebdfe3b22185d46b08f00ac9d7b01284e168c212919891289396", + "sha256:23b9fbb2f5dd9e630db70fbe47d963c7779e9c81830869bd7d137c2dc1ad05fb", + "sha256:26a6a9837589c42b16693cf7bf836f5d42218f44d198f9343dd71d3164ceeeac", + "sha256:2a21c97efcbb9f255d5c12a96ae14da873233597dfd00a3a0c4ce5b3e5e79704", + "sha256:2e2c38c2a4c5c634fe6c3c58a789712719fa1bf9b9d6ff5ebfce9a9e5b89c1ca", + "sha256:2fc47dc6185a83c8100b37acda27658fe4dbd33b7d5e7324111f6521008ab4fe", + "sha256:2fd17e3bb8058359fa61248c52c7b09a97cf3c820e54207a50af529876451808", + "sha256:352b2770097f41bff6029b280c0e03b217c2dcaddc40726f8f53ed58d8a85da4", + "sha256:3b74570d99126992d4b0f91fb87c586a574a5872651185de8297c6f90055ae42", + "sha256:3cb8a66b167b033ec72c3812ffc8441d4e9f5f78f5e31e54dcd4c90a4ca5bebc", + "sha256:3f9faef422cfbb8fd53716cd14ba95e2ef655400235c3dfad1b5f467ba179c8c", + "sha256:4b600e9a212ed59355813becbcf282cfda5c93678e15c25a0ef896b354423238", + "sha256:501ff052229cb79dd4c49c402f6cb03b5a40ae4771efc8bb2bfac9f6c3d3508f", + "sha256:56d51ae825d20d604583f82c9527d285e9e6d14f9a5516463d9705dab20c3740", + "sha256:597fec37c382a5442ffd471f66ce12d07d91b281fd474289356b1a0041bdf31d", + "sha256:5a48ac4d359f058474fadc2115f78a5cdac9988d4f99eae44917f36aa1476327", + "sha256:5b6cf796d9fcc9b37011d3f9936189b3c8074a02a4ed0c0fbbc126772c31a6d4", + "sha256:66f63278db425838b3c2b1c596654b31939427016ba030e951b292e32b99553e", + "sha256:69f3e3c08867a8e4856e92d7afb618b95cdee18e0bc1647b77599722c9a28911", + "sha256:6e2622844551945db81c26a02f27d94145b561f9d4b0c39ce7bfd2fda5776dac", + "sha256:6f77c4f042ad493cb8595e2f503c7a4fe44cd7bd59c7582fd6d78d7e7b8ec52c", + "sha256:74afabeeff415e35525bf7a4ecdab015f00e06456166a2eba7590e49f8db940e", + "sha256:750900a471d39a7eeba57580b11983030517a1f512c2cb287d5ad0fcf3aebd58", + "sha256:78fe11dbe37d92667c2c6e74379f75746dc947ee505555a0197cfba9a6d4f1a4", + "sha256:79a40771363c5e9f3a77f0e28b3302801db08040928146e6808b5b7a40749c88", + "sha256:7bd112be780928c7f493c1a192cd8c5fc2a2a7b52b790bc5a84203fb4381c6be", + "sha256:8a41514c1a779e2aa9a19f67aaadeb5cbddf0b2b508843fcd7bafdf4c6864005", + "sha256:9f2bee229715b6366f86a95d497c347c22ddffa2c7c96143b59a2aa5cc9eebbc", + "sha256:9fea3d0884e82d1e33226935dac990b967bef21315cbcc894605db3441347443", + "sha256:afb6dde6c11ea4525318e279cd93c8734b795ac8bb5dda0eedd9ebaca7fa23f1", + "sha256:b607489dd4a54de56984a0c7656247504bd5523d9d0ba799aef59d4add009484", + "sha256:b6e22630e89f0e8c12332b2b4c282cb01cf4da0d26795b7eae16702a608e7ca1", + "sha256:b9c01990d9015df2c6f818aa8f4297d42ee71c9502026bb074e713d496e26b67", + "sha256:bd15026f77420eb2b324dcb93551ad9c5f22fab2c150c286ef1dc1160f110203", + "sha256:c06fb43a51ccdff3b4006aafee9fcf15f63f23c580675f7734245ceb6b6a9e05", + "sha256:c76c81c52e1e08f12f4b6a07af2b96b9b15ea67ccdd40ae17019f1c373faa227", + "sha256:ccaf1b0c90435b6e430f5dd30a5aede4764942a695552eb3a4ab74ed63c5b8d3", + "sha256:cd1591329333daf94467e699e11015d9c944f44c94d2091f4ac493ced0119449", + "sha256:cd5b94d4819c0c89280b7c6109c7b788a576084bf0a480ae17c227b0bc41e109", + "sha256:d337bf94052856d1b330d5fcad44582a30c532a2463776e1651bd3294ee7e58b", + "sha256:dc251477eae03c20fae8db9c1c23ea2ebc47331bcd73927cdcaecd02af98d3c3", + "sha256:dc6d69f8829712a4fd799d2ac8d79bdeff651c2301b081fd5d3fe697bd5b4ab9", + "sha256:f2a213c1b699d3f5768a7272de720387ae0122f1becf0901ed6eaa1abd1baf6c", + "sha256:f3ad7f221d8a69d32d197e5968d798217a4feebe30144986af71ada8c548e9fa", + "sha256:f43e93057cf52a227eda401251c72b6fbe4756f35fa6bfebb5d73b86881e59b0", + "sha256:f68470edd70c3ac3b6cd5c2a22a8daf18415203ca1b036aaeb9b0fb6f54e8298", + "sha256:fa4b1af3e619b5b0b435e333f3967612db06351217c58bfb50cee5f003db2a5a", + "sha256:fc6b14e8602f59c6ba893980bea96571dd0ed83d8ebb9c4479d9ed5425d562e9" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.31" + }, + "sqlalchemy-serializer": { + "hashes": [ + "sha256:5e1f83fc6d8a4f7618100c1b9a6af949498210756b974527ec3c8c1ec7e1300f" + ], + "index": "pypi", + "version": "==1.4.12" + }, + "stack-data": { + "hashes": [ + "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", + "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695" + ], + "version": "==0.6.3" + }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version > '3.6'", + "version": "==0.10.2" + }, + "traitlets": { + "hashes": [ + "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", + "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f" + ], + "markers": "python_version >= '3.8'", + "version": "==5.14.3" + }, + "typing-extensions": { + "hashes": [ + "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", + "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + ], + "markers": "python_version >= '3.8'", + "version": "==4.12.2" + }, + "wcwidth": { + "hashes": [ + "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", + "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5" + ], + "version": "==0.2.13" + }, + "werkzeug": { + "hashes": [ + "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f", + "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==2.2.2" + }, + "zipp": { + "hashes": [ + "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19", + "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c" + ], + "markers": "python_version >= '3.8'", + "version": "==3.19.2" + } + }, + "develop": {} +} diff --git a/README.md b/README.md index c71c9b0f3..e69de29bb 100644 --- a/README.md +++ b/README.md @@ -1,357 +0,0 @@ -# Phase 4 Full-Stack Application Project Template - -## Learning Goals - -- Discuss the basic directory structure of a full-stack Flask/React application. -- Carry out the first steps in creating your Phase 4 project. - ---- - -## Introduction - -Fork and clone this lesson for a template for your full-stack application. Take -a look at the directory structure before we begin (NOTE: node_modules will be -generated in a subsequent step): - -```console -$ tree -L 2 -$ # the -L argument limits the depth at which we look into the directory structure -. -├── CONTRIBUTING.md -├── LICENSE.md -├── Pipfile -├── README.md -├── client -│ ├── README.md -│ ├── package.json -│ ├── public -│ └── src -└── server - ├── app.py - ├── config.py - ├── models.py - └── seed.py -``` - -A `migrations` folder will be added to the `server` directory in a later step. - -The `client` folder contains a basic React application, while the `server` -folder contains a basic Flask application. You will adapt both folders to -implement the code for your project . - -NOTE: If you did not previously install `tree` in your environment setup, MacOS -users can install this with the command `brew install tree`. WSL and Linux users -can run `sudo apt-get install tree` to download it as well. - -## Where Do I Start? - -Just as with your Phase 3 Project, this will likely be one of the biggest -projects you've undertaken so far. Your first task should be creating a Git -repository to keep track of your work and roll back any undesired changes. - -### Removing Existing Git Configuration - -If you're using this template, start off by removing the existing metadata for -Github and Canvas. Run the following command to carry this out: - -```console -$ rm -rf .git .canvas -``` - -The `rm` command removes files from your computer's memory. The `-r` flag tells -the console to remove _recursively_, which allows the command to remove -directories and the files within them. `-f` removes them permanently. - -`.git` contains this directory's configuration to track changes and push to -Github (you want to track and push _your own_ changes instead), and `.canvas` -contains the metadata to create a Canvas page from your Git repo. You don't have -the permissions to edit our Canvas course, so it's not worth keeping around. - -### Creating Your Own Git Repo - -First things first- rename this directory! Once you have an idea for a name, -move one level up with `cd ..` and run -`mv python-p4-project-template ` to change its name (replace - with an appropriate project directory name). - -> **Note: If you typed the `mv` command in a terminal within VS Code, you should -> close VS Code then reopen it.** - -> **Note: `mv` actually stands for "move", but your computer interprets this -> rename as a move from a directory with the old name to a directory with a new -> name.** - -`cd` back into your new directory and run `git init` to create a local git -repository. Add all of your local files to version control with `git add --all`, -then commit them with `git commit -m'initial commit'`. (You can change the -message here- this one is just a common choice.) - -Navigate to [GitHub](https://github.com). In the upper-right corner of the page, -click on the "+" dropdown menu, then select "New repository". Enter the name of -your local repo, choose whether you would like it to be public or private, make -sure "Initialize this repository with a README" is unchecked (you already have -one), then click "Create repository". - -Head back to the command line and enter -`git remote add origin git@github.com:github-username/new-repository-name.git`. -NOTE: Replace `github-username` with your github username, and -`new-repository-name` with the name of your new repository. This command will -map the remote repository to your local repository. Finally, push your first -commit with `git push -u origin main`. - -Your project is now version-controlled locally and online. This will allow you -to create different versions of your project and pick up your work on a -different machine if the need arises. - ---- - -## Setup - -### `server/` - -The `server/` directory contains all of your backend code. - -`app.py` is your Flask application. You'll want to use Flask to build a simple -API backend like we have in previous modules. You should use Flask-RESTful for -your routes. You should be familiar with `models.py` and `seed.py` by now, but -remember that you will need to use Flask-SQLAlchemy, Flask-Migrate, and -SQLAlchemy-Serializer instead of SQLAlchemy and Alembic in your models. - -The project contains a default `Pipfile` with some basic dependencies. You may -adapt the `Pipfile` if there are additional dependencies you want to add for -your project. - -To download the dependencies for the backend server, run: - -```console -pipenv install -pipenv shell -``` - -You can run your Flask API on [`localhost:5555`](http://localhost:5555) by -running: - -```console -python server/app.py -``` - -Check that your server serves the default route `http://localhost:5555`. You -should see a web page with the heading "Project Server". - -### `client/` - -The `client/` directory contains all of your frontend code. The file -`package.json` has been configured with common React application dependencies, -include `react-router-dom`. The file also sets the `proxy` field to forward -requests to `"http://localhost:5555". Feel free to change this to another port- -just remember to configure your Flask app to use another port as well! - -To download the dependencies for the frontend client, run: - -```console -npm install --prefix client -``` - -You can run your React app on [`localhost:3000`](http://localhost:3000) by -running: - -```sh -npm start --prefix client -``` - -Check that your the React client displays a default page -`http://localhost:3000`. You should see a web page with the heading "Project -Client". - -## Generating Your Database - -NOTE: The initial project directory structure does not contain the `instance` or -`migrations` folders. Change into the `server` directory: - -```console -cd server -``` - -Then enter the commands to create the `instance` and `migrations` folders and -the database `app.db` file: - -``` -flask db init -flask db upgrade head -``` - -Type `tree -L 2` within the `server` folder to confirm the new directory -structure: - -```console -. -├── app.py -├── config.py -├── instance -│ └── app.db -├── migrations -│ ├── README -│ ├── __pycache__ -│ ├── alembic.ini -│ ├── env.py -│ ├── script.py.mako -│ └── versions -├── models.py -└── seed.py -``` - -Edit `models.py` and start creating your models. Import your models as needed in -other modules, i.e. `from models import ...`. - -Remember to regularly run -`flask db revision --autogenerate -m''`, replacing -`` with an appropriate message, and `flask db upgrade head` -to track your modifications to the database and create checkpoints in case you -ever need to roll those modifications back. - -> **Tip: It's always a good idea to start with an empty revision! This allows -> you to roll all the way back while still holding onto your database. You can -> create this empty revision with `flask db revision -m'Create DB'`.** - -If you want to seed your database, now would be a great time to write out your -`seed.py` script and run it to generate some test data. Faker has been included -in the Pipfile if you'd like to use that library. - ---- - -#### `config.py` - -When developing a large Python application, you might run into a common issue: -_circular imports_. A circular import occurs when two modules import from one -another, such as `app.py` and `models.py`. When you create a circular import and -attempt to run your app, you'll see the following error: - -```console -ImportError: cannot import name -``` - -If you're going to need an object in multiple modules like `app` or `db`, -creating a _third_ module to instantiate these objects can save you a great deal -of circular grief. Here's a good start to a Flask config file (you may need more -if you intend to include features like authentication and passwords): - -```py -# Standard library imports - -# Remote library imports -from flask import Flask -from flask_cors import CORS -from flask_migrate import Migrate -from flask_restful import Api -from flask_sqlalchemy import SQLAlchemy -from sqlalchemy import MetaData - -# Local imports - -# Instantiate app, set attributes -app = Flask(__name__) -app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' -app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -app.json.compact = False - -# Define metadata, instantiate db -metadata = MetaData(naming_convention={ - "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", -}) -db = SQLAlchemy(metadata=metadata) -migrate = Migrate(app, db) -db.init_app(app) - -# Instantiate REST API -api = Api(app) - -# Instantiate CORS -CORS(app) - -``` - -Now let's review that last line... - -#### CORS - -CORS (Cross-Origin Resource Sharing) is a system that uses HTTP headers to -determine whether resources from different servers-of-origin can be accessed. If -you're using the fetch API to connect your frontend to your Flask backend, you -need to configure CORS on your Flask application instance. Lucky for us, that -only takes one line: - -```py -CORS(app) - -``` - -By default, Flask-CORS enables CORS on all routes in your application with all -fetching servers. You can also specify the resources that allow CORS. The -following specifies that routes beginning with `api/` allow CORS from any -originating server: - -```py -CORS(app, resources={r"/api/*": {"origins": "*"}}) - -``` - -You can also set this up resource-by-resource by importing and using the -`@cross_origin` decorator: - -```py -@app.route("/") -@cross_origin() -def howdy(): - return "Howdy partner!" - -``` - ---- - -## Updating Your README.md - -`README.md` is a Markdown file that describes your project. These files can be -used in many different ways- you may have noticed that we use them to generate -entire Canvas lessons- but they're most commonly used as homepages for online -Git repositories. **When you develop something that you want other people to -use, you need to have a README.** - -Markdown is not a language that we cover in Flatiron's Software Engineering -curriculum, but it's not a particularly difficult language to learn (if you've -ever left a comment on Reddit, you might already know the basics). Refer to the -cheat sheet in this lesson's resources for a basic guide to Markdown. - -### What Goes into a README? - -This README should serve as a template for your own- go through the important -files in your project and describe what they do. Each file that you edit (you -can ignore your migration files) should get at least a paragraph. Each function -should get a small blurb. - -You should descibe your application first, and with a good level of detail. The -rest should be ordered by importance to the user. (Probably routes next, then -models.) - -Screenshots and links to resources that you used throughout are also useful to -users and collaborators, but a little more syntactically complicated. Only add -these in if you're feeling comfortable with Markdown. - ---- - -## Conclusion - -A lot of work goes into a full-stack application, but it all relies on concepts -that you've practiced thoroughly throughout this phase. Hopefully this template -and guide will get you off to a good start with your Phase 4 Project. - -Happy coding! - ---- - -## Resources - -- [Setting up a respository - Atlassian](https://www.atlassian.com/git/tutorials/setting-up-a-repository) -- [Create a repo- GitHub Docs](https://docs.github.com/en/get-started/quickstart/create-a-repo) -- [Markdown Cheat Sheet](https://www.markdownguide.org/cheat-sheet/) -- [Python Circular Imports - StackAbuse](https://stackabuse.com/python-circular-imports/) -- [Flask-CORS](https://flask-cors.readthedocs.io/en/latest/) diff --git a/client/src/components/App.js b/client/src/components/App.js index af444c5b1..cb87fe779 100644 --- a/client/src/components/App.js +++ b/client/src/components/App.js @@ -1,8 +1,36 @@ -import React, { useEffect, useState } from "react"; -import { Switch, Route } from "react-router-dom"; +import React from 'react'; +import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; +import Login from './components/AuthForms/Login'; +import Register from './components/AuthForms/Register'; +import UserDetails from './components/User/UserDetails'; +import UserList from './components/User/UserList'; +import UserReview from './components/User/UserReview'; +import UserSignup from './components/User/UserSignup'; +import Header from './components/Header'; +import ReviewForm from './components/ReviewForm'; +import TravelGuideDetail from './components/TravelGuideDetail'; +import TravelGuideList from './components/TravelGuideList'; +import './App.css'; -function App() { - return

Project Client

; -} +const App = () => { + return ( + +
+
+ + + + + + + + + + + +
+
+ ); +}; export default App; diff --git a/client/src/components/AuthForms/Login.js b/client/src/components/AuthForms/Login.js new file mode 100644 index 000000000..05a1b624f --- /dev/null +++ b/client/src/components/AuthForms/Login.js @@ -0,0 +1,49 @@ +// Login.js +import React, { useState } from 'react'; +import api from '../../services/api'; + +const Login = () => { + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + + const handleSubmit = async (event) => { + event.preventDefault(); + try { + const response = await api.post('/login', { username, password }); + // Handle successful login (e.g., store token in local storage) + console.log('Login successful:', response.data); + } catch (error) { + console.error('Error logging in:', error); + } + }; + + return ( +
+
+ +
+
+ +
+ +
+ ); +}; + +export default Login; diff --git a/client/src/components/AuthForms/Register.js b/client/src/components/AuthForms/Register.js new file mode 100644 index 000000000..b6821ccb3 --- /dev/null +++ b/client/src/components/AuthForms/Register.js @@ -0,0 +1,61 @@ +// Register.js +import React, { useState } from 'react'; +import api from '../../services/api'; + +const Register = () => { + const [username, setUsername] = useState(''); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + + const handleSubmit = async (event) => { + event.preventDefault(); + try { + const response = await api.post('/register', { username, email, password }); + // Handle successful registration (e.g., navigate to login page) + console.log('Registration successful:', response.data); + } catch (error) { + console.error('Error registering:', error); + } + }; + + return ( +
+
+ +
+
+ +
+
+ +
+ +
+ ); +}; + +export default Register; diff --git a/client/src/components/Header.js b/client/src/components/Header.js new file mode 100644 index 000000000..3cf37fcc4 --- /dev/null +++ b/client/src/components/Header.js @@ -0,0 +1,20 @@ +// Header.js +import React from 'react'; +import { Link } from 'react-router-dom'; + +const Header = () => { + return ( +
+ +
+ ); +}; + +export default Header; diff --git a/client/src/components/ReviewForm.js b/client/src/components/ReviewForm.js new file mode 100644 index 000000000..619abae43 --- /dev/null +++ b/client/src/components/ReviewForm.js @@ -0,0 +1,48 @@ +// ReviewForm.js +import React, { useState } from 'react'; +import api from '../services/api'; + +const ReviewForm = ({ guideId }) => { + const [rating, setRating] = useState(''); + const [comment, setComment] = useState(''); + + const handleSubmit = async (event) => { + event.preventDefault(); + try { + await api.post(`/guides/${guideId}/reviews`, { rating, comment }); + // Optionally: Refresh guide details after submitting review + // Or navigate to a different page + } catch (error) { + console.error('Error submitting review:', error); + } + }; + + return ( +
+
+ +
+
+