diff --git a/PawPanion/Controllers/RecordController.cs b/PawPanion/Controllers/RecordController.cs index 6b76c0c..f90c883 100644 --- a/PawPanion/Controllers/RecordController.cs +++ b/PawPanion/Controllers/RecordController.cs @@ -30,6 +30,28 @@ public IActionResult GetRecordsByPetId(int petId) return Ok(post); } + [HttpGet] + public IActionResult GetAllByDate() + { + var post = _recordRepository.GetAllRecordsByDate(); + if (post == null) + { + NotFound(); + } + return Ok(post); + } + + //[HttpGet("most-recent/{petId}")] + //public IActionResult NewestRecordByPetId(int id) + //{ + // var post = _recordRepository.MostRecentRecordByPetId(id); + // if (post == null) + // { + // NotFound(); + // } + // return Ok(post); + //} + [HttpPost] public IActionResult Post(Record record) { diff --git a/PawPanion/Repositories/IRecordRepository.cs b/PawPanion/Repositories/IRecordRepository.cs index 2de9223..992efd4 100644 --- a/PawPanion/Repositories/IRecordRepository.cs +++ b/PawPanion/Repositories/IRecordRepository.cs @@ -6,6 +6,8 @@ namespace PawPanion.Repositories public interface IRecordRepository { List GetPetRecordsByPetId(int petId); + List MostRecentRecordByPetId(int petId); + List GetAllRecordsByDate(); void Add(Record record); void Delete(int id); } diff --git a/PawPanion/Repositories/RecordRepository.cs b/PawPanion/Repositories/RecordRepository.cs index cc64ed5..1a8370a 100644 --- a/PawPanion/Repositories/RecordRepository.cs +++ b/PawPanion/Repositories/RecordRepository.cs @@ -88,6 +88,9 @@ FROM Record r + + + public void Add(Record record) { using (var conn = Connection) @@ -128,5 +131,160 @@ public void Delete(int id) } } + public List MostRecentRecordByPetId(int petId) + { + using (var conn = Connection) + { + conn.Open(); + using (var cmd = conn.CreateCommand()) + { + cmd.CommandText = @" + SELECT TOP 1 r.Id AS RecordId, r.RecordTypeId, r.PetId AS RecordPetId, r.VetId AS RVetId, r.Date, Weight, Medication, Illness, + Diet, Note, + rt.Id AS RTId, rt.Name AS RecordTypeName, + p.Id AS PetId, p.Name AS PetName, Breed, IsMale, Birthdate, p.OwnerId AS PetOwnerId, p.IsDog, p.ImageLocation AS PetImageLocation, + v.Id AS VetId, v.Name AS VetName, v.ImageLocation AS VetImageLocation, v.Email AS VetEmail, v.Phone AS VetPhone, v.IsVet AS VetIsVet, + o.Id AS OwnerId, o.Name AS OwnerName, o.Email AS OwnerEmail, o.Phone AS OwnerPhone, o.ImageLocation AS OwnerImageLocation, o.IsVet AS OwnerIsVet + FROM Record r + JOIN Pet p ON p.Id = r.PetId + JOIN RecordType rt ON r.RecordTypeId = rt.Id + JOIN [User] v ON r.VetId = v.Id + JOIN [User] o ON p.OwnerId = o.Id + WHERE r.PetId = @Id + ORDER BY Date DESC"; + + DbUtils.AddParameter(cmd, "@Id", petId); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + List records = new(); + + while (reader.Read()) + { + records.Add(new Record() + { + Id = DbUtils.GetInt(reader, "RecordId"), + RecordTypeId = DbUtils.GetInt(reader, "RecordTypeId"), + RecordType = new RecordType() + { + Id = DbUtils.GetInt(reader, "RTId"), + Name = DbUtils.GetString(reader, "RecordTypeName"), + }, + PetId = DbUtils.GetInt(reader, "RecordPetId"), + Pet = new Pet() + { + Id = DbUtils.GetInt(reader, "PetId"), + Name = DbUtils.GetString(reader, "PetName"), + Breed = DbUtils.GetString(reader, "Breed"), + IsMale = reader.GetBoolean(reader.GetOrdinal("IsMale")), + Birthdate = DbUtils.GetDateTime(reader, "Birthdate"), + OwnerId = DbUtils.GetInt(reader, "PetOwnerId"), + IsDog = reader.GetBoolean(reader.GetOrdinal("IsDog")), + ImageLocation = DbUtils.GetString(reader, "PetImageLocation") + }, + VetId = DbUtils.GetInt(reader, "RVetId"), + Vet = new User() + { + Id = DbUtils.GetInt(reader, "VetId"), + Name = DbUtils.GetString(reader, "VetName"), + ImageLocation = DbUtils.GetString(reader, "VetImageLocation"), + Email = DbUtils.GetString(reader, "VetEmail"), + Phone = DbUtils.GetString(reader, "VetPhone"), + IsVet = reader.GetBoolean(reader.GetOrdinal("VetIsVet")) + }, + Date = DbUtils.GetDateTime(reader, "Date"), + Weight = (float)reader.GetDouble(reader.GetOrdinal("Weight")), + Medication = DbUtils.GetString(reader, "Medication"), + Illness = DbUtils.GetString(reader, "Illness"), + Diet = DbUtils.GetString(reader, "Diet"), + Note = DbUtils.GetString(reader, "Note") + }); + } + return records; + } + } + } + } + + + public List GetAllRecordsByDate() + { + using (var conn = Connection) + { + conn.Open(); + using (var cmd = conn.CreateCommand()) + { + cmd.CommandText = @" + SELECT r.Id AS RecordId, r.RecordTypeId, r.PetId AS RecordPetId, r.VetId AS RVetId, r.Date, Weight, Medication, Illness, + Diet, Note, + rt.Id AS RTId, rt.Name AS RecordTypeName, + p.Id AS PetId, p.Name AS PetName, Breed, IsMale, Birthdate, p.OwnerId AS PetOwnerId, p.IsDog, p.ImageLocation AS PetImageLocation, + v.Id AS VetId, v.Name AS VetName, v.ImageLocation AS VetImageLocation, v.Email AS VetEmail, v.Phone AS VetPhone, v.IsVet AS VetIsVet, + o.Id AS OwnerId, o.Name AS OwnerName, o.Email AS OwnerEmail, o.Phone AS OwnerPhone, o.ImageLocation AS OwnerImageLocation, o.IsVet AS OwnerIsVet + FROM Record r + JOIN Pet p ON p.Id = r.PetId + JOIN RecordType rt ON r.RecordTypeId = rt.Id + JOIN [User] v ON r.VetId = v.Id + JOIN [User] o ON p.OwnerId = o.Id + ORDER BY Date DESC + "; + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + List records = new List(); + + while (reader.Read()) + { + Record record = new Record + { + Id = DbUtils.GetInt(reader, "RecordId"), + RecordTypeId = DbUtils.GetInt(reader, "RecordTypeId"), + RecordType = new RecordType() + { + Id = DbUtils.GetInt(reader, "RTId"), + Name = DbUtils.GetString(reader, "RecordTypeName"), + }, + PetId = DbUtils.GetInt(reader, "RecordPetId"), + Pet = new Pet() + { + Id = DbUtils.GetInt(reader, "PetId"), + Name = DbUtils.GetString(reader, "PetName"), + Breed = DbUtils.GetString(reader, "Breed"), + IsMale = reader.GetBoolean(reader.GetOrdinal("IsMale")), + Birthdate = DbUtils.GetDateTime(reader, "Birthdate"), + OwnerId = DbUtils.GetInt(reader, "PetOwnerId"), + IsDog = reader.GetBoolean(reader.GetOrdinal("IsDog")), + ImageLocation = DbUtils.GetString(reader, "PetImageLocation") + }, + VetId = DbUtils.GetInt(reader, "RVetId"), + Vet = new User() + { + Id = DbUtils.GetInt(reader, "VetId"), + Name = DbUtils.GetString(reader, "VetName"), + ImageLocation = DbUtils.GetString(reader, "VetImageLocation"), + Email = DbUtils.GetString(reader, "VetEmail"), + Phone = DbUtils.GetString(reader, "VetPhone"), + IsVet = reader.GetBoolean(reader.GetOrdinal("VetIsVet")) + }, + Date = DbUtils.GetDateTime(reader, "Date"), + Weight = (float)reader.GetDouble(reader.GetOrdinal("Weight")), + Medication = DbUtils.GetString(reader, "Medication"), + Illness = DbUtils.GetString(reader, "Illness"), + Diet = DbUtils.GetString(reader, "Diet"), + Note = DbUtils.GetString(reader, "Note") + }; + + + records.Add(record); + } + + return records; + } + } + } + } + + + } } \ No newline at end of file diff --git a/PawPanion/client/package-lock.json b/PawPanion/client/package-lock.json index 1238d7b..30622f5 100644 --- a/PawPanion/client/package-lock.json +++ b/PawPanion/client/package-lock.json @@ -11,9 +11,14 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "bootstrap": "^5.2.3", "firebase": "^8.7.1", "react": "^18.2.0", + "react-bootstrap": "^2.7.2", + "react-bootstrap-sidebar-menu": "^2.0.3", "react-dom": "^18.2.0", + "react-icons": "^4.7.1", + "react-pro-sidebar": "^1.0.0", "react-router-dom": "^6.8.0", "react-scripts": "5.0.1", "reactstrap": "^9.1.5", @@ -2127,6 +2132,170 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.5.tgz", + "integrity": "sha512-xE7/hyLHJac7D2Ve9dKroBBZqBT7WuPQmWcq7HSGb84sUuP4mlOWoB8dvVfD9yk5DHkU1m6RW7xSoDtnQHNQeA==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/plugin-syntax-jsx": "^7.17.12", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/serialize": "^1.1.1", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.1.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz", + "integrity": "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==", + "dependencies": { + "@emotion/memoize": "^0.8.0", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "stylis": "4.1.3" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", + "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "dependencies": { + "@emotion/memoize": "^0.8.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "node_modules/@emotion/react": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.5.tgz", + "integrity": "sha512-TZs6235tCJ/7iF6/rvTaOH4oxQg2gMAcdHemjwLKIjKz4rRuYe1HJ2TQJKnAcRAfOUDdU8XoDadCe1rl72iv8A==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.5", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", + "dependencies": { + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/unitless": "^0.8.0", + "@emotion/utils": "^1.2.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" + }, + "node_modules/@emotion/styled": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.5.tgz", + "integrity": "sha512-8EP6dD7dMkdku2foLoruPCNkRevzdcBaY6q0l0OsbyJK+x8D9HWjX27ARiSIKNF634hY9Zdoedh8bJCiva8yZw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.5", + "@emotion/is-prop-valid": "^1.2.0", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", + "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + }, "node_modules/@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -3583,6 +3752,17 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@react-aria/ssr": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.4.1.tgz", + "integrity": "sha512-NmhoilMDyIfQiOSdQgxpVH2tC2u85Y0mVijtBNbI9kcDYLEiW/r6vKYVKtkyU+C4qobXhGMPfZ70PTc0lysSVA==", + "dependencies": { + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, "node_modules/@remix-run/router": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.1.tgz", @@ -3591,6 +3771,37 @@ "node": ">=14" } }, + "node_modules/@restart/hooks": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz", + "integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==", + "dependencies": { + "dequal": "^2.0.2" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.1.tgz", + "integrity": "sha512-cMI9DdqZV5VGEyANYM4alHK9/2Lh/mKZAMydztMl6PBLm6EetFbwE2RfYqliloR+EtEULlI4TiZk/XPhQAovxw==", + "dependencies": { + "@babel/runtime": "^7.20.7", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.4.1", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3909,6 +4120,14 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@testing-library/dom": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", @@ -4592,6 +4811,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -4658,6 +4885,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, + "node_modules/@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, "node_modules/@types/ws": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", @@ -5876,6 +6108,24 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "node_modules/bootstrap": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", + "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.6" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -6958,6 +7208,14 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -8508,6 +8766,11 @@ "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -9161,6 +9424,19 @@ "he": "bin/he" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -9531,6 +9807,14 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -14489,6 +14773,23 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/prop-types-extra/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -14694,6 +14995,47 @@ "node": ">=14" } }, + "node_modules/react-bootstrap": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.7.2.tgz", + "integrity": "sha512-WDSln+mG4RLLFO01stkj2bEx/3MF4YihK9D/dWnHaSxOiQZLbhhlf95D2Jb20X3t2m7vMxRe888FVrfLJoGmmA==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "@restart/hooks": "^0.4.6", + "@restart/ui": "^1.4.1", + "@types/react-transition-group": "^4.4.4", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-bootstrap-sidebar-menu": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/react-bootstrap-sidebar-menu/-/react-bootstrap-sidebar-menu-2.0.3.tgz", + "integrity": "sha512-lm5LrOcExFQtKaLSSZ8K2VSnqiROsDgY6WRnitev1eELlrBAyumrdk6ckq5vG8iCeN1GUVKUahIG21LyAOoWRA==", + "dependencies": { + "react-bootstrap": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -14833,11 +15175,24 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, + "node_modules/react-icons": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz", + "integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "node_modules/react-popper": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", @@ -14852,6 +15207,21 @@ "react-dom": "^16.8.0 || ^17 || ^18" } }, + "node_modules/react-pro-sidebar": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/react-pro-sidebar/-/react-pro-sidebar-1.0.0.tgz", + "integrity": "sha512-TAU3vHj0rYHSLWdZksiWte59dwh3rweaFY+dXri+y8mtlbQalxnNTG11k9wRCiaMa0IGPmIIbdY1E1yoHBUd/A==", + "dependencies": { + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "@popperjs/core": "^2.11.6", + "classnames": "^2.3.2" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -16117,6 +16487,11 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -16661,6 +17036,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -19174,6 +19563,133 @@ "integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==", "requires": {} }, + "@emotion/babel-plugin": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.5.tgz", + "integrity": "sha512-xE7/hyLHJac7D2Ve9dKroBBZqBT7WuPQmWcq7HSGb84sUuP4mlOWoB8dvVfD9yk5DHkU1m6RW7xSoDtnQHNQeA==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/plugin-syntax-jsx": "^7.17.12", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/serialize": "^1.1.1", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.1.3" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + } + } + }, + "@emotion/cache": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz", + "integrity": "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==", + "requires": { + "@emotion/memoize": "^0.8.0", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "stylis": "4.1.3" + } + }, + "@emotion/hash": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", + "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + }, + "@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "requires": { + "@emotion/memoize": "^0.8.0" + } + }, + "@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "@emotion/react": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.5.tgz", + "integrity": "sha512-TZs6235tCJ/7iF6/rvTaOH4oxQg2gMAcdHemjwLKIjKz4rRuYe1HJ2TQJKnAcRAfOUDdU8XoDadCe1rl72iv8A==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.5", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "hoist-non-react-statics": "^3.3.1" + } + }, + "@emotion/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", + "requires": { + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/unitless": "^0.8.0", + "@emotion/utils": "^1.2.0", + "csstype": "^3.0.2" + } + }, + "@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" + }, + "@emotion/styled": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.5.tgz", + "integrity": "sha512-8EP6dD7dMkdku2foLoruPCNkRevzdcBaY6q0l0OsbyJK+x8D9HWjX27ARiSIKNF634hY9Zdoedh8bJCiva8yZw==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.5", + "@emotion/is-prop-valid": "^1.2.0", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0" + } + }, + "@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "requires": {} + }, + "@emotion/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + }, + "@emotion/weak-memoize": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", + "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + }, "@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -20287,11 +20803,43 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@react-aria/ssr": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.4.1.tgz", + "integrity": "sha512-NmhoilMDyIfQiOSdQgxpVH2tC2u85Y0mVijtBNbI9kcDYLEiW/r6vKYVKtkyU+C4qobXhGMPfZ70PTc0lysSVA==", + "requires": { + "@swc/helpers": "^0.4.14" + } + }, "@remix-run/router": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.1.tgz", "integrity": "sha512-+eun1Wtf72RNRSqgU7qM2AMX/oHp+dnx7BHk1qhK5ZHzdHTUU4LA1mGG1vT+jMc8sbhG3orvsfOmryjzx2PzQw==" }, + "@restart/hooks": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz", + "integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==", + "requires": { + "dequal": "^2.0.2" + } + }, + "@restart/ui": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.1.tgz", + "integrity": "sha512-cMI9DdqZV5VGEyANYM4alHK9/2Lh/mKZAMydztMl6PBLm6EetFbwE2RfYqliloR+EtEULlI4TiZk/XPhQAovxw==", + "requires": { + "@babel/runtime": "^7.20.7", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.4.1", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -20486,6 +21034,14 @@ "loader-utils": "^2.0.0" } }, + "@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "requires": { + "tslib": "^2.4.0" + } + }, "@testing-library/dom": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", @@ -21053,6 +21609,14 @@ "@types/react": "*" } }, + "@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "requires": { + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -21119,6 +21683,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, + "@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, "@types/ws": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", @@ -22021,6 +22590,12 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "bootstrap": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", + "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==", + "requires": {} + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -22788,6 +23363,11 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -23954,6 +24534,11 @@ "pkg-dir": "^4.1.0" } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -24396,6 +24981,21 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, "hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -24670,6 +25270,14 @@ "side-channel": "^1.0.4" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -28068,6 +28676,22 @@ } } }, + "prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "requires": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, "protobufjs": { "version": "6.11.3", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", @@ -28210,6 +28834,33 @@ "whatwg-fetch": "^3.6.2" } }, + "react-bootstrap": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.7.2.tgz", + "integrity": "sha512-WDSln+mG4RLLFO01stkj2bEx/3MF4YihK9D/dWnHaSxOiQZLbhhlf95D2Jb20X3t2m7vMxRe888FVrfLJoGmmA==", + "requires": { + "@babel/runtime": "^7.17.2", + "@restart/hooks": "^0.4.6", + "@restart/ui": "^1.4.1", + "@types/react-transition-group": "^4.4.4", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, + "react-bootstrap-sidebar-menu": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/react-bootstrap-sidebar-menu/-/react-bootstrap-sidebar-menu-2.0.3.tgz", + "integrity": "sha512-lm5LrOcExFQtKaLSSZ8K2VSnqiROsDgY6WRnitev1eELlrBAyumrdk6ckq5vG8iCeN1GUVKUahIG21LyAOoWRA==", + "requires": { + "react-bootstrap": "^2.0.0" + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -28315,11 +28966,22 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, + "react-icons": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz", + "integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==", + "requires": {} + }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "react-popper": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", @@ -28329,6 +28991,17 @@ "warning": "^4.0.2" } }, + "react-pro-sidebar": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/react-pro-sidebar/-/react-pro-sidebar-1.0.0.tgz", + "integrity": "sha512-TAU3vHj0rYHSLWdZksiWte59dwh3rweaFY+dXri+y8mtlbQalxnNTG11k9wRCiaMa0IGPmIIbdY1E1yoHBUd/A==", + "requires": { + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "@popperjs/core": "^2.11.6", + "classnames": "^2.3.2" + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -29252,6 +29925,11 @@ "postcss-selector-parser": "^6.0.4" } }, + "stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -29661,6 +30339,17 @@ "which-boxed-primitive": "^1.0.2" } }, + "uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "requires": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + } + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", diff --git a/PawPanion/client/package.json b/PawPanion/client/package.json index efc566b..53c0b50 100644 --- a/PawPanion/client/package.json +++ b/PawPanion/client/package.json @@ -7,9 +7,14 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "bootstrap": "^5.2.3", "firebase": "^8.7.1", "react": "^18.2.0", + "react-bootstrap": "^2.7.2", + "react-bootstrap-sidebar-menu": "^2.0.3", "react-dom": "^18.2.0", + "react-icons": "^4.7.1", + "react-pro-sidebar": "^1.0.0", "react-router-dom": "^6.8.0", "react-scripts": "5.0.1", "reactstrap": "^9.1.5", diff --git a/PawPanion/client/public/index.html b/PawPanion/client/public/index.html index aa069f2..20c301c 100644 --- a/PawPanion/client/public/index.html +++ b/PawPanion/client/public/index.html @@ -1,21 +1,22 @@ - - - - - - - - - - - React App - - - -
- - - + + + \ No newline at end of file diff --git a/PawPanion/client/public/main.scss b/PawPanion/client/public/main.scss new file mode 100644 index 0000000..e4cd93f --- /dev/null +++ b/PawPanion/client/public/main.scss @@ -0,0 +1,3 @@ +$primary: purple; + +@import "../node_modules/bootstrap/scss/bootstrap" \ No newline at end of file diff --git a/PawPanion/client/src/App.js b/PawPanion/client/src/App.js index fc02517..ff9783e 100644 --- a/PawPanion/client/src/App.js +++ b/PawPanion/client/src/App.js @@ -4,6 +4,7 @@ import { Spinner } from 'reactstrap'; import ApplicationViews from "./components/ApplicationViews"; import { onLoginStatusChange } from "./modules/authManager"; import Header from "./components/Header"; +import 'bootstrap/dist/css/bootstrap.min.css'; function App() { const [isLoggedIn, setIsLoggedIn] = useState(null); diff --git a/PawPanion/client/src/components/Header.js b/PawPanion/client/src/components/Header.js index 4c751b2..c66e812 100644 --- a/PawPanion/client/src/components/Header.js +++ b/PawPanion/client/src/components/Header.js @@ -29,7 +29,7 @@ export default function Header({ isLoggedIn }) { return (
- + Pawpanion diff --git a/PawPanion/client/src/components/userViews/HomePage.css b/PawPanion/client/src/components/userViews/HomePage.css new file mode 100644 index 0000000..a248508 --- /dev/null +++ b/PawPanion/client/src/components/userViews/HomePage.css @@ -0,0 +1,65 @@ +@import url('https://fonts.googleapis.com/css2?family=Fredoka+One&display=swap'); + +body { + /* background-image: url("paper.gif"); */ + background-size: cover; + background: linear-gradient(180deg, rgba(102, 153, 255, 1) 35%, rgba(42, 113, 255, 1) 100%) no-repeat center fixed !important; +} + +.welcome-user { + color: rgb(255, 255, 255); + padding: 1.5rem rem 0 0 3rem; + margin-top: 3rem; + margin-left: 3.7rem; + font-family: 'Fredoka One', cursive; + font-size: 2.5rem; + letter-spacing: 1px; +} + +.homepage-labels { + color: rgb(255, 255, 255); + padding: 1.5rem rem 0 0 3rem; + margin-top: 3rem; + margin-left: 3.7rem; + font-family: 'Fredoka One', cursive; + font-size: 3rem; + letter-spacing: 1px; +} + +.vetHomeContainer { + margin: auto; + max-width: 900px; + border: black solid 2px; +} + +.pet-container { + margin-left: 3rem !important; + margin-top: 1px !important; +} + +.pet-list-container { + display: flex; + justify-content: space-between; + padding: 0 8rem; +} + +.pet-list-container-owner { + display: flex; +} + +.add-pet { + font-size: 2rem; + margin: auto; + margin-bottom: 320px; + margin-left: 1.7rem; +} + + +.grow { + transition: all .2s ease-in-out; +} + +/* a:hover { + background-color: yellow; + transition: all .2s ease-in-out; +} */ \ No newline at end of file diff --git a/PawPanion/client/src/components/userViews/HomePage.js b/PawPanion/client/src/components/userViews/HomePage.js index f70539a..401acbf 100644 --- a/PawPanion/client/src/components/userViews/HomePage.js +++ b/PawPanion/client/src/components/userViews/HomePage.js @@ -4,6 +4,7 @@ import { useEffect, useState } from "react"; import { VetHomePage } from "./VetHomePage"; import { OwnerHomePage } from "./OwnerHomePage"; import { getCurrentUserByFirebaseId } from "../../modules/userManager"; +import "./HomePage.css" export const HomePage = () => { const [user, setUser] = useState([]) @@ -26,6 +27,7 @@ export const HomePage = () => { return ( ); diff --git a/PawPanion/client/src/components/userViews/OwnerHomePage.js b/PawPanion/client/src/components/userViews/OwnerHomePage.js index c10706d..5af46bd 100644 --- a/PawPanion/client/src/components/userViews/OwnerHomePage.js +++ b/PawPanion/client/src/components/userViews/OwnerHomePage.js @@ -1,48 +1,132 @@ import "firebase/auth"; import { getUserPets } from "../../modules/petManager"; import React, { useEffect, useState } from "react"; -import { Button } from "reactstrap"; import { Link, useNavigate } from "react-router-dom"; +import Button from 'react-bootstrap/Button'; +import Card from 'react-bootstrap/Card'; +import { getAllRecords } from "../../modules/recordManager"; +import { factGenerator } from "./PetFacts"; export const OwnerHomePage = () => { const [ownerPets, setOwnerPets] = useState([]); + const [records, setRecords] = useState([]); const navigate = useNavigate(); - const getAll = () => { + useEffect(() => { getUserPets().then(ownerPets => setOwnerPets(ownerPets)); - } + }, []); useEffect(() => { - getAll(); + getAllRecords().then(records => setRecords(records)); }, []); - return ( -
+ const randomFact = factGenerator() + + return (<> +
Did you know?
+ {randomFact} +
Your Pets
+
+ {ownerPets.map((pet) => { - const petPic = pet.imageLocation - - /* - if (!pet.imageLocation && pet.isDog) { - petPic === //DEFAULT DOG PIC URL - } else if (!pet.imageLocation && !pet.isDog) { - petPic === //DEFAULT CAT PIC URL - } else { - petPic === pet.imageLocation - } - */ - - return
-
+ + const petRecord = records.find(record => record.petId === pet.id) + + //const petPic = pet.imageLocation + + + // if (!pet.imageLocation && pet.isDog) { + // petPic === //DEFAULT DOG PIC URL + // } else if (!pet.imageLocation && !pet.isDog) { + // petPic === //DEFAULT CAT PIC URL + // } else { + // petPic === pet.imageLocation + // } + + + + var petDate = pet.birthdate; + petDate = petDate.split('T')[0]; + + return (<> + + + + + {pet.name} + DOB: {petDate} + + {pet.breed} + + {petRecord?.weight ? `Weight: ${petRecord?.weight}` : ""} + + + {petRecord?.medication ? `Recent medication(s): ${petRecord?.medication}` : ""} + + + {petRecord?.illness ? `Recent conditions: ${petRecord?.illness}` : ""} + + + {petRecord?.diet ? `Diet plan: ${petRecord?.diet}` : ""} + + + {petRecord?.note ? `Most recent vet notes: + ${petRecord?.note} + Submitted on ${petRecord?.date}` : ""} + + + + + + + + + + ) + })} + +
+ add a pet
+
+
+ ) +} + + +{/* + + + Profile + + {pet.name} + + + {petDate} + + + {pet.breed} + + + + + */} + +{/*
{pet.name}
-
{pet.birthdate}
+
{petDate}
{pet.breed}
-
View All Records
-
- })} -
- ) -} \ No newline at end of file +
View All Records
*/} \ No newline at end of file diff --git a/PawPanion/client/src/components/userViews/PetFacts.js b/PawPanion/client/src/components/userViews/PetFacts.js new file mode 100644 index 0000000..baabc9e --- /dev/null +++ b/PawPanion/client/src/components/userViews/PetFacts.js @@ -0,0 +1,19 @@ +export const factGenerator = () => { + const randomFact = [ + "A dog’s nose print is unique, much like a person’s fingerprint.", + "Dogs’ noses can sense heat/thermal radiation, which explains why blind or deaf dogs can still hunt.", + "Yawning is contagious—even for dogs. Research shows that the sound of a human yawn can trigger one from your dog.", + "Dogs are not colorblind. They can see blue and yellow.", + "The Bloodhound’s sense of smell is so accurate that the results of its tracking can be used as evidence in a court of law.", + "House cats share 95.6% of their genetic makeup with tigers.", + "The oldest cat to ever live was Creme Puff, who lived to be 38 years and 3 days old.", + "Cats have a whopping 32 muscles in each of their ears, allowing them to swivel their ears to hone in on the exact source of a noise.", + "Abraham Lincoln, the 16th President of the United States, absolutely loved cats and would play with them for hours. He owned several cats during this time in the White House", + "Cats usually sleep around an average of 15 hours per day. This means that a cat spends roughly 70% of their lives sleeping.", + "In Ancient Egypt, members of a family would shave their eyebrows in mourning if their cat died." + ]; + + const random = Math.floor(Math.random() * randomFact.length); + const answer = randomFact[random] + return (`${answer}`) +} \ No newline at end of file diff --git a/PawPanion/client/src/components/userViews/VetHomePage.js b/PawPanion/client/src/components/userViews/VetHomePage.js index 37c49a8..7aa75e7 100644 --- a/PawPanion/client/src/components/userViews/VetHomePage.js +++ b/PawPanion/client/src/components/userViews/VetHomePage.js @@ -2,6 +2,7 @@ import { getAllPets } from "../../modules/petManager"; import React, { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { Card, Button } from "reactstrap"; +import "./HomePage.css" export const VetHomePage = () => { const [pets, setPets] = useState([]); @@ -16,15 +17,20 @@ export const VetHomePage = () => { }, []); return ( -
-
- {pets.map((pet) => { - return
-
{pet.owner.name} {pet.owner.phone} {pet.name} -
-
- })} -
+ +
+ {pets.map((pet) => { + return ( +
+
{pet.owner.name}
{pet.owner.phone}
+
{pet.name} + +
+ +
+ ) + })}
+ ) } \ No newline at end of file diff --git a/PawPanion/client/src/index.js b/PawPanion/client/src/index.js index 35aa907..9667262 100644 --- a/PawPanion/client/src/index.js +++ b/PawPanion/client/src/index.js @@ -20,4 +20,4 @@ root.render( // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); +reportWebVitals(); \ No newline at end of file diff --git a/PawPanion/client/src/modules/recordManager.js b/PawPanion/client/src/modules/recordManager.js index ced5913..f75d6b5 100644 --- a/PawPanion/client/src/modules/recordManager.js +++ b/PawPanion/client/src/modules/recordManager.js @@ -79,4 +79,43 @@ export const getRecordById = (id) => { } }); }); -}; \ No newline at end of file +}; + +export const getAllRecords = () => { + return getToken().then((token) => { + return fetch(baseUrl, { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + }, + }).then((res) => { + if (res.ok) { + return res.json(); + } else { + throw new Error( + "An unknown error occurred.", + ); + } + }); + }); +}; + + +// export const getNewestRecordByPetId = (pet) => { +// return getToken().then((token) => { +// return fetch(`${baseUrl}/most-recent/${pet.id}`, { +// method: "GET", +// headers: { +// Authorization: `Bearer ${token}`, +// }, +// }).then((res) => { +// if (res.ok) { +// return res.json(); +// } else { +// throw new Error( +// "An unknown error occured.", +// ); +// } +// }); +// }); +// }; \ No newline at end of file