This commit is contained in:
Jessica_Faro 2025-10-23 14:18:36 -03:00
parent 7f14cf16b7
commit e4386c1776
7 changed files with 676 additions and 566 deletions

258
package-lock.json generated
View File

@ -15,9 +15,11 @@
"@testing-library/jest-dom": "^6.8.0", "@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0", "@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"@tiptap/core": "^3.7.2",
"@tiptap/extension-placeholder": "^3.7.1", "@tiptap/extension-placeholder": "^3.7.1",
"@tiptap/pm": "^3.7.2",
"@tiptap/react": "^3.7.1", "@tiptap/react": "^3.7.1",
"@tiptap/starter-kit": "^3.7.1", "@tiptap/starter-kit": "^3.7.2",
"apexcharts": "^5.3.4", "apexcharts": "^5.3.4",
"bootstrap": "^5.3.8", "bootstrap": "^5.3.8",
"bootstrap-icons": "^1.13.1", "bootstrap-icons": "^1.13.1",
@ -17781,39 +17783,39 @@
} }
}, },
"node_modules/@tiptap/core": { "node_modules/@tiptap/core": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.7.2.tgz",
"integrity": "sha512-jB6R8EGI34QUmV7EhtE+JVpjbZ6Wa0dcf0LNS36X9V7FtDQcnxl7ekRs/ftELt/6qOjubRdyhaID0wNdJVmFtw==", "integrity": "sha512-fJwNpTx0aq4UU0HNkxPvPYfNBcTHQ/q5xBUdOB5Mgu6clwGES38jVsNNSudB8g53APUmJIS+2fJbkxl3V+0jww==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/pm": "^3.7.1" "@tiptap/pm": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-blockquote": { "node_modules/@tiptap/extension-blockquote": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.7.2.tgz",
"integrity": "sha512-UPIne4kD8hwhadPtapn0WfJCNiF+b3ftNYiC1BpNfti5NmM0sXuqOOC0WnVgGgsNuJp4hd+4PMp42InlD6/1aw==", "integrity": "sha512-8rNDh1E1ratex9KicvNNnjJGtF313Kpf5hXHOUcIm8FQwvA/0Tu6jq7r6VgESMyo95R3EmzRpnCYQef+zDm6OQ==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-bold": { "node_modules/@tiptap/extension-bold": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.7.2.tgz",
"integrity": "sha512-XZRt1blYGpqVlcBo+PKH1mlbsqdc5KsWi/ZsPBV3Ajg/Vx5d6SAY4wK6CW1SpotE1wWucUhfAmXddhBFvYzaUA==", "integrity": "sha512-bwCn9lQEXnEi7LfIx3G/oaH4I0ZapAgrHzLCNJH/tNgRKVWym1H1Oa8PlkiFDbalWOdUkbgeAUqUaIB13k408Q==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-bubble-menu": { "node_modules/@tiptap/extension-bubble-menu": {
@ -17834,64 +17836,64 @@
} }
}, },
"node_modules/@tiptap/extension-bullet-list": { "node_modules/@tiptap/extension-bullet-list": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.7.2.tgz",
"integrity": "sha512-AO7EVAftvzSw7Sftp36P+HNedxjygMpobYNTBQzHfGljRZh8VDhIUzwyP1OsmlrcCbBxsrjMZLrmk/ozsALq0g==", "integrity": "sha512-OHYYXKjmxisLQws0tW8Dz14PcyIJmaed7eypZvIm/R3hxa/7lJY/2EM/Ti5g/w1U8WPBEH1hX3icRtiulserKw==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/extension-list": "^3.7.1" "@tiptap/extension-list": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-code": { "node_modules/@tiptap/extension-code": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.7.2.tgz",
"integrity": "sha512-ZRarYvgQ16ZrzKox/iW3bVr5IVNBsD0yjU5S7GVmlRgRQ8lhsTloLk9Gu05uuZ6dOoL3qApLA8+W7w8sxZJ35w==", "integrity": "sha512-J8FaCiKJJnHvQiPcbfbUtc5RNmGx/Gui/K5CDMPc17jhCiQ9JhR9idRPREV24Z2t7GujWX7LG6ZDDR82pSns+g==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-code-block": { "node_modules/@tiptap/extension-code-block": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.7.2.tgz",
"integrity": "sha512-/Ov81QXEn6AOiiSUFlM57a+YSye/Lkhvgy303+CEGtDuFVU/SJ0tDsgmSYzkP5q6DIVQLAXp5WkxEo02GnYHgQ==", "integrity": "sha512-TfixutvvbGCrSSCsfDK/PBm6A5FIzcPTSVDrmmsiAfqldj/Woy1T42dads+wv9SjKG06GlWDwYtDGAk2Uun8NA==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1", "@tiptap/core": "^3.7.2",
"@tiptap/pm": "^3.7.1" "@tiptap/pm": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-document": { "node_modules/@tiptap/extension-document": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.7.2.tgz",
"integrity": "sha512-b7NHWseJSvhhbsiSWjQgiJcs6FUJiEJocfhazDiWAOk5ELQ6+oiIe7ecEgDqBmafk9oziV9r7u9OAgyeyP3JBA==", "integrity": "sha512-OrHl402v2FWCUKR1Xi5MTNBAkKYQh7mtpw/WlJDFnk5z1qHLqz4UIcbGilDYzVPrNUZPhA1p3c+V5UUVUFzUfg==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-dropcursor": { "node_modules/@tiptap/extension-dropcursor": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.7.2.tgz",
"integrity": "sha512-wZT3bPeNJAasOvNr6tUZAwXFeKlQEToSnVAjFiBzJwLDonuK8ZaAiBCDQgqEQSlP3HsEE4/qkERBNrdyAT26CQ==", "integrity": "sha512-79y6M9pJYwqcqBHIWoomfptJp0QB/TP3Y+2NOL09sMNeSdUgmz5pCVObA4H48YMkoB0EcUtux2IUOM66e4nsJA==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/extensions": "^3.7.1" "@tiptap/extensions": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-floating-menu": { "node_modules/@tiptap/extension-floating-menu": {
@ -17910,70 +17912,70 @@
} }
}, },
"node_modules/@tiptap/extension-gapcursor": { "node_modules/@tiptap/extension-gapcursor": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.7.2.tgz",
"integrity": "sha512-1UrZEaqruWPLdgYsAm4au7BAyTDjaNRP0E7UIoEoGsq+MAS2MM3g4suXMzu+l3ZIayrSy98N3T8DIUG+U6+mww==", "integrity": "sha512-vCLo2dL2SfeWjh/gJKDiu0/fz6OF7obGTJvHg/yStkoUqlAEiwKoyHP/NXeTGYJMzZzUi0kY9DtTEJdGFvphuQ==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/extensions": "^3.7.1" "@tiptap/extensions": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-hard-break": { "node_modules/@tiptap/extension-hard-break": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.7.2.tgz",
"integrity": "sha512-pEvRjWexMNxXH5FOy3EhzyMFDFHrRTWOgZbWAxliKDg2dFEJ50e9KcCMDs87e7++V753lEKnFTmz/9WaH7cwcQ==", "integrity": "sha512-nNDo+5S1yRQ3JkBM+gwpEEVZ/Kw9qWoG/cpShyGYDHo1/y8MgO+VI0kSb/LuBTw7g+jmNXdf+ZaRRI/pXsUihg==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-heading": { "node_modules/@tiptap/extension-heading": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.7.2.tgz",
"integrity": "sha512-rOUou6b0+5E+DAmEMTC/mlKTLiOr4D0LKzBfqBLQ3zUyZPZabOKzN0L+4MaLNR2CkXy/Ae4du5ucHGrGOWzVrQ==", "integrity": "sha512-eH/G66FIRlTQz4MhEmlNNNQgVTxhoqlkyFzgeG5aipIplYOdYa5Y6Wl0NF4xqr1jAHGLAK6LaYS4FXp3TE7LyA==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-horizontal-rule": { "node_modules/@tiptap/extension-horizontal-rule": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.7.2.tgz",
"integrity": "sha512-f4lXW/LHuJBF11PIrWdNAzTmlapV4fVujJ5eCsLAkpzhx3izVrDW/WlKRrkGUCy/qQT4v7BbHNa5JYlKDzDo0Q==", "integrity": "sha512-pN+1hJAVVP3uqtpZ5Rm7z5XUB/NGprK6wExJ04xG117E4rTVcaEb1FnMILY3J3A5XbdC3vHX+cblR8mOl1PAMw==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1", "@tiptap/core": "^3.7.2",
"@tiptap/pm": "^3.7.1" "@tiptap/pm": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-italic": { "node_modules/@tiptap/extension-italic": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.7.2.tgz",
"integrity": "sha512-Bm6eOtcafc5kjE357GlvIY2hNTRRAkb8D5SRm8zYlVB0fiLto+r15Ht+DTOmLiQKEGtEArQ/C8Rh2j09UdH2vA==", "integrity": "sha512-1tfF37LvKgA5hg09UBgOjdMLNRb1C6keIOBF0r5oHKeWPYOf4z3j5IU9PsFUoOn53XRMb1aiD/TNbGPyoT3Fyw==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-link": { "node_modules/@tiptap/extension-link": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.7.2.tgz",
"integrity": "sha512-6+0/mo+EKDiA1d1pDZSsf/51ZOwdFnN35yF/4celxdr/JL4aupvtttIjGAtWd37h50cadYSL4F1uacKs7yyh8Q==", "integrity": "sha512-9K54PxBiDSWAMfICqkb8jcQ6cL7vDAtjTk0zqBw4d+XuaUy0FC9QUdbx7r1Pkbf36K1/ApbvM9a7qpOirWk8Xw==",
"dependencies": { "dependencies": {
"linkifyjs": "^4.3.2" "linkifyjs": "^4.3.2"
}, },
@ -17982,69 +17984,69 @@
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1", "@tiptap/core": "^3.7.2",
"@tiptap/pm": "^3.7.1" "@tiptap/pm": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-list": { "node_modules/@tiptap/extension-list": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.7.2.tgz",
"integrity": "sha512-E93oXkV2vsZThsix0OA7RiHNLIMGi+w9ASKZ+8TGB69oy32yujnnZz6YVhTVVDPOw8rCP5CnOPhJbgdcqByr0A==", "integrity": "sha512-/tYHmEkOGcVweAc9ZgnAXkzua5aJfu7TjZcKTq5fmDt6x9MY1eY1+egS7D9hVR2sUSAC10VgXmYdYPDsKF3p2g==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1", "@tiptap/core": "^3.7.2",
"@tiptap/pm": "^3.7.1" "@tiptap/pm": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-list-item": { "node_modules/@tiptap/extension-list-item": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.7.2.tgz",
"integrity": "sha512-qkXfWRBusJCId9VhRo9vihcrmxvJ83fkzYWI0LiefJCT1LKfMaeInFNxIsFeUU4q9nR0mhZo7ES3E2+Tk0U3Mw==", "integrity": "sha512-962TFsx4eF5NMyLVhGFGF/btt5j3MipPhDiUsxzBgnlW8o5OonVepb9cDrqpEDQ2/wLvheWnCKuvmG7umasldQ==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/extension-list": "^3.7.1" "@tiptap/extension-list": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-list-keymap": { "node_modules/@tiptap/extension-list-keymap": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.7.2.tgz",
"integrity": "sha512-3WyzWge/g6FoxMTkoAARtMJyIYQbpclNX48HyAqdwjJXuLmz3qckEnJEXo47CvJlRsNAlcDJniRS9j5SVJupRw==", "integrity": "sha512-1du9eo+NPIkuRT258yUn9bovhip556aJo/yDtRbswEVNScP1E8y/kFRWvw0HD7/YWcNqok1ZteoSwShWnKAXRQ==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/extension-list": "^3.7.1" "@tiptap/extension-list": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-ordered-list": { "node_modules/@tiptap/extension-ordered-list": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.7.2.tgz",
"integrity": "sha512-iX3DhTwFp84fiCNSF7+kl/sq6orXq2QFcV2AH+CvL+d0WW1STYmmVmE26gHEjyY82QfpvLZYUCEG6RSYpxFIZw==", "integrity": "sha512-Tu61/JXh1RRd3Kb+s7A7jmpnB+w1pqGSRfMXBtYHDHDIGyXu255ru7soX44lJfHGq/zYcTFSHGSsi8o23QONJg==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/extension-list": "^3.7.1" "@tiptap/extension-list": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-paragraph": { "node_modules/@tiptap/extension-paragraph": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.7.2.tgz",
"integrity": "sha512-L5dsppKKo46MN3Go5vzqqzjPX89pz1lIkIUN3IhU+KmAHg1TklfR7FQkiIFIIV2rb2ZLuLpD/JcNsZAUmJTW5Q==", "integrity": "sha512-HmDuAixTcvP4A/v6OLkh/C6nB86i7/DRNswBf/Udak8TgWUIcSUK0iActxxm5+B3MZTSf3U87JzyI6IeuElLIQ==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-placeholder": { "node_modules/@tiptap/extension-placeholder": {
@ -18060,58 +18062,58 @@
} }
}, },
"node_modules/@tiptap/extension-strike": { "node_modules/@tiptap/extension-strike": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.7.2.tgz",
"integrity": "sha512-Ctqk/SfmGd3hFCDr4/OH0Dnja19UWUrUEY62pwM7JCkbY/Y9QwPLSO32L6KyamwUDek9SL/ATjRPz6GLp0P7hg==", "integrity": "sha512-I1G+4vZbCBTpAMmyVwaO8cLBJgXEf1DyEzc0B+HhTJiBa9qA9OKgRQEGFgisxu1kggjbzB6+d0+taHfjsZC1SQ==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-text": { "node_modules/@tiptap/extension-text": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.7.2.tgz",
"integrity": "sha512-m+8FJrFAllJYuzLbEXJ9AztobxmWBTjWorkHcMHBLAbY2ytmAhIM1u3ExtOn9DjvnIT6MffCaq0i/KjhSBYJlA==", "integrity": "sha512-sKaeGYNP1+bAe2rvmzWLW5qH9DsSFOJlOUEOFchR0OX0rC7bbGS6/KuyAq0w6UkL+cMJnDyAbv3KeD2WEA192w==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extension-underline": { "node_modules/@tiptap/extension-underline": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.7.2.tgz",
"integrity": "sha512-tyx7ZM2ll8DclKe9Ea/vPyqaZBgnJfIbKBOpecpzawDaJ5ocjwywmYNduevOhw327X2/i8LIQBsPuIOJselcUQ==", "integrity": "sha512-GDpUZllTD7uIdHjTzYJ6i4jUgCeviW40SCpLVVv1xH0gj1t1xu0Rnxmk+bXkF2XNe8jPXkMCgYNr6DR6eO8roQ==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1" "@tiptap/core": "^3.7.2"
} }
}, },
"node_modules/@tiptap/extensions": { "node_modules/@tiptap/extensions": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.7.2.tgz",
"integrity": "sha512-O7eq3frqh7kn/J2P+lpx8blBQrIQxt21J3NvlQJhW5nXIECdo2ox8SQcEfli0EqMSwZCZTdVufdFBkWfIRXhRg==", "integrity": "sha512-FaToSdU9fhQk2swkaXrAQNgdaE0dwLbUHcvilW5F4xTpQfZ3J535u5U2TUYf+f9KKSV5fTmD4QGNY9qxY7ihTg==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ueberdosis" "url": "https://github.com/sponsors/ueberdosis"
}, },
"peerDependencies": { "peerDependencies": {
"@tiptap/core": "^3.7.1", "@tiptap/core": "^3.7.2",
"@tiptap/pm": "^3.7.1" "@tiptap/pm": "^3.7.2"
} }
}, },
"node_modules/@tiptap/pm": { "node_modules/@tiptap/pm": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.7.2.tgz",
"integrity": "sha512-t3n054kplRtRYn8pDnzF/prDUccF7QX7jPYLsYBpLn3+d59J5KKkBmOpPExUGE8kZkNoLfwffAFj6NBfqOu+Xg==", "integrity": "sha512-i2fvXDapwo/TWfHM6STYEbkYyF3qyfN6KEBKPrleX/Z80G5bLxom0gB79TsjLNxTLi6mdf0vTHgAcXMG1avc2g==",
"dependencies": { "dependencies": {
"prosemirror-changeset": "^2.3.0", "prosemirror-changeset": "^2.3.0",
"prosemirror-collab": "^1.3.1", "prosemirror-collab": "^1.3.1",
@ -18164,34 +18166,34 @@
} }
}, },
"node_modules/@tiptap/starter-kit": { "node_modules/@tiptap/starter-kit": {
"version": "3.7.1", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.7.1.tgz", "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.7.2.tgz",
"integrity": "sha512-ZYgA3BkASQmHyoDlUYKFPEpCzIcn/FP/Sb+Ic2L7gt2gOC7zvWAVc/2yIbiFuq+48s+5U/KJqDiXn2hiLwXxpA==", "integrity": "sha512-43GwI+2Mtc/ci7J4eJOE02wZxp5KIsDTMMb0peNksPcEGaURGdDhav9zbAW24NRjRxU7Auk/zaQu9O8+ZE0v0A==",
"dependencies": { "dependencies": {
"@tiptap/core": "^3.7.1", "@tiptap/core": "^3.7.2",
"@tiptap/extension-blockquote": "^3.7.1", "@tiptap/extension-blockquote": "^3.7.2",
"@tiptap/extension-bold": "^3.7.1", "@tiptap/extension-bold": "^3.7.2",
"@tiptap/extension-bullet-list": "^3.7.1", "@tiptap/extension-bullet-list": "^3.7.2",
"@tiptap/extension-code": "^3.7.1", "@tiptap/extension-code": "^3.7.2",
"@tiptap/extension-code-block": "^3.7.1", "@tiptap/extension-code-block": "^3.7.2",
"@tiptap/extension-document": "^3.7.1", "@tiptap/extension-document": "^3.7.2",
"@tiptap/extension-dropcursor": "^3.7.1", "@tiptap/extension-dropcursor": "^3.7.2",
"@tiptap/extension-gapcursor": "^3.7.1", "@tiptap/extension-gapcursor": "^3.7.2",
"@tiptap/extension-hard-break": "^3.7.1", "@tiptap/extension-hard-break": "^3.7.2",
"@tiptap/extension-heading": "^3.7.1", "@tiptap/extension-heading": "^3.7.2",
"@tiptap/extension-horizontal-rule": "^3.7.1", "@tiptap/extension-horizontal-rule": "^3.7.2",
"@tiptap/extension-italic": "^3.7.1", "@tiptap/extension-italic": "^3.7.2",
"@tiptap/extension-link": "^3.7.1", "@tiptap/extension-link": "^3.7.2",
"@tiptap/extension-list": "^3.7.1", "@tiptap/extension-list": "^3.7.2",
"@tiptap/extension-list-item": "^3.7.1", "@tiptap/extension-list-item": "^3.7.2",
"@tiptap/extension-list-keymap": "^3.7.1", "@tiptap/extension-list-keymap": "^3.7.2",
"@tiptap/extension-ordered-list": "^3.7.1", "@tiptap/extension-ordered-list": "^3.7.2",
"@tiptap/extension-paragraph": "^3.7.1", "@tiptap/extension-paragraph": "^3.7.2",
"@tiptap/extension-strike": "^3.7.1", "@tiptap/extension-strike": "^3.7.2",
"@tiptap/extension-text": "^3.7.1", "@tiptap/extension-text": "^3.7.2",
"@tiptap/extension-underline": "^3.7.1", "@tiptap/extension-underline": "^3.7.2",
"@tiptap/extensions": "^3.7.1", "@tiptap/extensions": "^3.7.2",
"@tiptap/pm": "^3.7.1" "@tiptap/pm": "^3.7.2"
}, },
"funding": { "funding": {
"type": "github", "type": "github",

View File

@ -10,9 +10,11 @@
"@testing-library/jest-dom": "^6.8.0", "@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0", "@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"@tiptap/core": "^3.7.2",
"@tiptap/extension-placeholder": "^3.7.1", "@tiptap/extension-placeholder": "^3.7.1",
"@tiptap/pm": "^3.7.2",
"@tiptap/react": "^3.7.1", "@tiptap/react": "^3.7.1",
"@tiptap/starter-kit": "^3.7.1", "@tiptap/starter-kit": "^3.7.2",
"apexcharts": "^5.3.4", "apexcharts": "^5.3.4",
"bootstrap": "^5.3.8", "bootstrap": "^5.3.8",
"bootstrap-icons": "^1.13.1", "bootstrap-icons": "^1.13.1",

View File

@ -1,130 +1,131 @@
// src/PagesMedico/DoctorRelatorioManager.jsx
import API_KEY from '../components/utils/apiKeys'; import API_KEY from '../components/utils/apiKeys';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import {useState, useEffect} from 'react' import { useState, useEffect } from 'react';
import { useAuth } from '../components/utils/AuthProvider'; import { useAuth } from '../components/utils/AuthProvider';
import { GetPatientByID } from '../components/utils/Functions-Endpoints/Patient'; import { GetPatientByID } from '../components/utils/Functions-Endpoints/Patient';
import { GetDoctorByID } from '../components/utils/Functions-Endpoints/Doctor';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import html2pdf from 'html2pdf.js'; import html2pdf from 'html2pdf.js';
import TiptapViewer from './TiptapViewer'; import TiptapViewer from './TiptapViewer';
const DoctorRelatorioManager = () => { const DoctorRelatorioManager = () => {
const navigate = useNavigate() const navigate = useNavigate();
const {getAuthorizationHeader} = useAuth(); const { getAuthorizationHeader } = useAuth();
let authHeader = getAuthorizationHeader() const authHeader = getAuthorizationHeader();
const [RelatoriosFiltrados, setRelatorios] = useState([]) const [RelatoriosFiltrados, setRelatorios] = useState([]);
const [PacientesComRelatorios, setPacientesComRelatorios] = useState([]) const [PacientesComRelatorios, setPacientesComRelatorios] = useState([]);
const [showModal, setShowModal] = useState(false) const [MedicosComRelatorios, setMedicosComRelatorios] = useState([]);
const [index, setIndex] = useState() const [showModal, setShowModal] = useState(false);
// 1º useEffect: Busca os dados dos pacientes após carregar os relatórios const [index, setIndex] = useState();
useEffect( () => {
let pacientesDosRelatorios = []
const ListarPacientes = async () => { // busca lista de relatórios
useEffect(() => {
const fetchReports = async () => {
try {
var myHeaders = new Headers();
myHeaders.append('apikey', API_KEY);
myHeaders.append('Authorization', authHeader);
var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' };
const res = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?select=*", requestOptions);
const data = await res.json();
setRelatorios(data || []);
} catch (err) {
console.error('Erro listar relatórios', err);
setRelatorios([]);
}
};
fetchReports();
}, [authHeader]);
// depois que RelatoriosFiltrados mudar, busca pacientes e médicos correspondentes
useEffect(() => {
const fetchRelData = async () => {
const pacientes = [];
const medicos = [];
for (let i = 0; i < RelatoriosFiltrados.length; i++) { for (let i = 0; i < RelatoriosFiltrados.length; i++) {
let relatorio = RelatoriosFiltrados[i]; const rel = RelatoriosFiltrados[i];
let paciente_id = relatorio.patient_id; // paciente
const paciente = await GetPatientByID(paciente_id, authHeader); try {
console.log(paciente) const pacienteRes = await GetPatientByID(rel.patient_id, authHeader);
if (paciente.length > 0) { pacientes.push(Array.isArray(pacienteRes) ? pacienteRes[0] : pacienteRes);
pacientesDosRelatorios.push(paciente[0]); } catch (err) {
pacientes.push(null);
}
// médico: tenta created_by ou requested_by id se existir
try {
const doctorId = rel.created_by || rel.requested_by || null;
if (doctorId) {
// se created_by é id (uuid) usamos GetDoctorByID, senão se requested_by for nome, guardamos nome
const docRes = await GetDoctorByID(doctorId, authHeader);
medicos.push(Array.isArray(docRes) ? docRes[0] : docRes);
} else {
medicos.push({ full_name: rel.requested_by || '' });
}
} catch (err) {
medicos.push({ full_name: rel.requested_by || '' });
} }
} }
setPacientesComRelatorios(pacientesDosRelatorios); setPacientesComRelatorios(pacientes);
setMedicosComRelatorios(medicos);
};
if (RelatoriosFiltrados.length > 0) fetchRelData();
else {
setPacientesComRelatorios([]);
setMedicosComRelatorios([]);
} }
ListarPacientes()
}, [RelatoriosFiltrados, authHeader]); }, [RelatoriosFiltrados, authHeader]);
// NOVO: useEffect para logar PacientesComRelatorios após a atualização
useEffect(() => {
console.log(PacientesComRelatorios, 'aqui')
}, [PacientesComRelatorios])
// 2º useEffect: Busca a lista de relatórios const BaixarPDFdoRelatorio = (nome_paciente) => {
useEffect(() => { const elemento = document.getElementById("folhaA4");
var myHeaders = new Headers(); const opt = { margin: 0, filename: `relatorio_${nome_paciente || "paciente"}.pdf`, html2canvas: { scale: 2 }, jsPDF: { unit: "mm", format: "a4", orientation: "portrait" } };
myHeaders.append("apikey", API_KEY); html2pdf().set(opt).from(elemento).save();
myHeaders.append("Authorization", authHeader);
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?patient_id&status", requestOptions)
.then(response => response.json())
.then(data => { setRelatorios(data); console.log(data) })
.catch(error => console.log('error', error));
}, [authHeader])
const BaixarPDFdoRelatorio = (nome_paciente) => {
const elemento = document.getElementById("folhaA4"); // tua div do relatório
const opt = {
margin: 0,
filename: `relatorio_${nome_paciente || "paciente"}.pdf`,
html2canvas: { scale: 2 },
jsPDF: { unit: "mm", format: "a4", orientation: "portrait" },
}; };
html2pdf().set(opt).from(elemento).save();
} return (
return (
<div> <div>
{showModal && ( {showModal && (
<div className="modal" > <div className="modal">
<div className="modal-dialog modal-tabela-relatorio"> <div className="modal-dialog modal-tabela-relatorio">
<div className="modal-content"> <div className="modal-content">
<div className="modal-header text-white"> <div className="modal-header text-white">
<h5 className="modal-title ">Relatório de {PacientesComRelatorios[index]?.full_name} </h5> <h5 className="modal-title ">Relatório de {PacientesComRelatorios[index]?.full_name}</h5>
<button <button type="button" className="btn-close" onClick={() => setShowModal(false)}></button>
type="button" </div>
className="btn-close" <div className="modal-body">
onClick={() => setShowModal(false)} <div id="folhaA4">
></button> <div id='header-relatorio'>
</div> <p>Clinica Rise up</p>
<div className="modal-body"> <p>Dr - CRM/SP 123456</p>
<div id="folhaA4"> <p>Avenida - (79) 9 4444-4444</p>
<div id='header-relatorio'> </div>
<p>Clinica Rise up</p>
<p>Dr - CRM/SP 123456</p> <div id='infoPaciente'>
<p>Avenida - (79) 9 4444-4444</p> <p>Paciente: {PacientesComRelatorios[index]?.full_name}</p>
</div> <p>Data de nascimento: {PacientesComRelatorios[index]?.birth_date}</p>
<div id='infoPaciente'> <p>Data do exame: {RelatoriosFiltrados[index]?.due_at || ''}</p>
<p>Paciente: {PacientesComRelatorios[index]?.full_name}</p> {/* Exibe conteúdo salvo (content_html) */}
<p>Data de nascimento: {PacientesComRelatorios[index]?.birth_date} </p> <p style={{ marginTop: '15px', fontWeight: 'bold' }}>Conteúdo do Relatório:</p>
<p>Data do exame: {}</p> <TiptapViewer htmlContent={RelatoriosFiltrados[index]?.content_html || RelatoriosFiltrados[index]?.content || 'Relatório não preenchido.'} />
<p>Exame: {RelatoriosFiltrados[index]?.exam}</p> </div>
{/* INÍCIO DA MUDANÇA (da resposta anterior) */}
<p style={{ marginTop: '15px', fontWeight: 'bold' }}>Conteúdo do Relatório:</p> <div>
<TiptapViewer <p>Dr {MedicosComRelatorios[index]?.full_name || RelatoriosFiltrados[index]?.requested_by}</p>
htmlContent={ <p>Emitido em: {RelatoriosFiltrados[index]?.created_at || '—'}</p>
RelatoriosFiltrados[index]?.content ||
RelatoriosFiltrados[index]?.diagnosis ||
RelatoriosFiltrados[index]?.conclusion ||
'Relatório não preenchido.'
}
/>
{/* FIM DA MUDANÇA */}
</div>
<div>
<p>Dr {RelatoriosFiltrados[index]?.required_by}</p>
<p>Emitido em: 0</p>
</div>
</div> </div>
</div> </div>
<div className="modal-footer"> </div>
<button className="btn btn-primary" onClick={() => BaixarPDFdoRelatorio(PacientesComRelatorios[index]?.full_name)}><i className='bi bi-file-pdf-fill'></i> baixar em pdf</button> <div className="modal-footer">
<button <button className="btn btn-primary" onClick={() => BaixarPDFdoRelatorio(PacientesComRelatorios[index]?.full_name)}><i className='bi bi-file-pdf-fill'></i> baixar em pdf</button>
type="button" <button type="button" className="btn btn-primary" onClick={() => { setShowModal(false) }}>Fechar</button>
className="btn btn-primary"
onClick={() => {setShowModal(false)}}
>
Fechar
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
)} )}
<div className="page-heading">
<h3>Lista de Relatórios</h3> <div className="page-heading"><h3>Lista de Relatórios</h3></div>
</div>
<div className="page-content"> <div className="page-content">
<section className="row"> <section className="row">
<div className="col-12"> <div className="col-12">
@ -132,114 +133,59 @@ fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?patient_id&statu
<div className="card-header d-flex justify-content-between align-items-center"> <div className="card-header d-flex justify-content-between align-items-center">
<h4 className="card-title mb-0">Relatórios Cadastrados</h4> <h4 className="card-title mb-0">Relatórios Cadastrados</h4>
<Link to={'criar'}> <Link to={'criar'}>
<button <button className="btn btn-primary"><i className="bi bi-plus-circle"></i> Adicionar Relatório</button>
className="btn btn-primary"
>
<i className="bi bi-plus-circle"></i> Adicionar Relatório
</button>
</Link> </Link>
</div> </div>
<div className="card-body"> <div className="card-body">
<div className="card p-3 mb-3"> <div className="card p-3 mb-3">
<h5 className="mb-3"> <h5 className="mb-3"><i className="bi bi-funnel-fill me-2 text-primary"></i> Filtros</h5>
<i className="bi bi-funnel-fill me-2 text-primary"></i>{" "} <div className="d-flex flex-nowrap align-items-center gap-2" style={{ overflowX: "auto", paddingBottom: "6px" }}>
Filtros <input type="text" className="form-control" placeholder="Buscar por nome..." style={{ minWidth: 250, maxWidth: 300, width: 260, flex: "0 0 auto" }} />
</h5>
<div
className="d-flex flex-nowrap align-items-center gap-2"
style={{ overflowX: "auto", paddingBottom: "6px" }}
>
<input
type="text"
className="form-control"
placeholder="Buscar por nome..."
style={{
minWidth: 250,
maxWidth: 300,
width: 260,
flex: "0 0 auto",
}}
/>
</div> </div>
</div> </div>
<div className="table-responsive"> <div className="table-responsive">
<table className="table table-striped table-hover"> <table className="table table-striped table-hover">
<thead> <thead>
<tr> <tr>
<th>Paciente</th> <th>Paciente</th>
<th>CPF</th> <th>Doutor</th>
<th>Exame</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{RelatoriosFiltrados.length > 0 ? ( {RelatoriosFiltrados.length > 0 ? (
RelatoriosFiltrados.map((relatorio, index) => ( RelatoriosFiltrados.map((relatorio, idx) => (
<tr key={relatorio.id}> <tr key={relatorio.id}>
<td className='infos-paciente'>{PacientesComRelatorios[idx]?.full_name}</td>
<td className='infos-paciente'>{PacientesComRelatorios[index]?.full_name}</td> <td className='infos-paciente'>{MedicosComRelatorios[idx]?.full_name || relatorio.requested_by || '-'}</td>
<td className='infos-paciente'>{PacientesComRelatorios[index]?.cpf}</td>
<td>{relatorio.exam}</td>
<td> <td>
<div className="d-flex gap-2"> <div className="d-flex gap-2">
<button className="btn btn-sm" style={{ backgroundColor: "#E6F2FF", color: "#004085" }} onClick={() => { setShowModal(true); setIndex(idx); }}>
<i className="bi bi-eye me-1"></i> Ver Detalhes
</button>
<button <button className="btn btn-sm" style={{ backgroundColor: "#FFF3CD", color: "#856404" }} onClick={() => navigate(`/medico/relatorios/${relatorio.id}/edit`)}>
className="btn btn-sm" <i className="bi bi-pencil me-1"></i> Editar
style={{ </button>
backgroundColor: "#E6F2FF", </div>
color: "#004085",
}}
onClick={() => {
setShowModal(true); setIndex(index)
}}
>
<i className="bi bi-eye me-1"></i> Ver Detalhes
</button>
<button
className="btn btn-sm"
style={{
backgroundColor: "#FFF3CD",
color: "#856404",
}}
onClick={() => {
// MANTIDO: Uso de string template para a navegação
navigate(`/medico/relatorios/${relatorio.id}/edit`)
}}
>
<i className="bi bi-pencil me-1"></i> Editar
</button>
</div>
</td> </td>
</tr> </tr>
)) ))
) : ( ) : (
<tr> <tr><td colSpan="8" className="text-center">Nenhum paciente encontrado.</td></tr>
<td colSpan="8" className="text-center">
Nenhum paciente encontrado.
</td>
</tr>
)} )}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</div> </div>
</div> </div>
) );
} };
export default DoctorRelatorioManager
export default DoctorRelatorioManager;

View File

@ -1,172 +1,153 @@
import React, { useEffect, useState } from 'react' // EditPageRelatorio.jsx
import { useParams, useNavigate } from 'react-router-dom' import React, { useEffect, useState } from 'react';
import API_KEY from '../components/utils/apiKeys' import { useParams, useNavigate } from 'react-router-dom';
import { useAuth } from '../components/utils/AuthProvider' import API_KEY from '../components/utils/apiKeys';
import TiptapEditor from '../PagesMedico/TiptapEditor' import { useAuth } from '../components/utils/AuthProvider';
import { GetPatientByID } from '../components/utils/Functions-Endpoints/Patient' import TiptapEditor from '../PagesMedico/TiptapEditor';
import { GetPatientByID } from '../components/utils/Functions-Endpoints/Patient';
import { GetDoctorByID } from '../components/utils/Functions-Endpoints/Doctor';
const EditPageRelatorio = () => { const EditPageRelatorio = () => {
const params = useParams() const params = useParams();
const navigate = useNavigate() const navigate = useNavigate();
const {getAuthorizationHeader} = useAuth() const { getAuthorizationHeader } = useAuth();
let authHeader = getAuthorizationHeader() const authHeader = getAuthorizationHeader();
const [loading, setLoading] = useState(true);
const [relatorioData, setRelatorioData] = useState({ const [report, setReport] = useState(null);
patient_id: '', const [patient, setPatient] = useState(null);
exam: '', const [doctor, setDoctor] = useState(null);
// Mantemos apenas os campos necessários para o fetch, mas não para edição direta na UI const [html, setHtml] = useState('');
required_by: '',
address_line: '',
content: '',
})
const [loading, setLoading] = useState(true)
const [patientData, setPatientData] = useState(null) // Armazena dados do paciente
const RelatorioID = params.id
// Modelo HTML do relatório para ser carregado no Tiptap se o conteúdo for novo/vazio
const generateReportModel = (report, patient) => {
// Escapa as aspas se necessário, mas para HTML simples não é crucial
const patientName = patient?.full_name || 'Paciente não encontrado';
const birthDate = patient?.birth_date || 'Data não informada';
const exam = report?.exam || 'Exame não especificado';
const generateTemplate = (r = {}, p = {}, d = {}) => {
const patientName = p?.full_name || '[NOME DO PACIENTE]';
const birthDate = p?.birth_date || '';
const exam = r?.exam || '';
const doctorName = d?.full_name || r?.requested_by || '';
return ` return `
<div> <div>
<p style="text-align: center; font-weight: bold;">Clinica Rise up</p> <p style="text-align:center; font-weight:bold;">Clinica Rise up</p>
<p style="text-align: center;">Dr - CRM/SP 123456</p> <p style="text-align:center;">Dr - CRM/SP 123456</p>
<p style="text-align: center;">Avenida - (79) 9 4444-4444</p> <p style="text-align:center;">Avenida - (79) 9 4444-4444</p>
<br> <br/>
<p><strong>Paciente:</strong> ${patientName}</p> <p><strong>Paciente:</strong> ${patientName}</p>
<p><strong>Data de nascimento:</strong> ${birthDate}</p> <p><strong>Data de nascimento:</strong> ${birthDate}</p>
<p><strong>Data do exame:</strong> </p> <p><strong>Data do exame:</strong></p>
<p><strong>Exame:</strong> ${exam}</p> <p><strong>Exame:</strong> ${exam}</p>
<br> <br/>
<p><strong>Conteúdo do Relatório:</strong></p> <p style="font-weight:bold;">Diagnóstico:</p>
<p>1</p> <p>${r?.diagnosis || ''}</p>
<br> <br/>
<p>Dr</p> <p style="font-weight:bold;">Conclusão:</p>
<p>${r?.conclusion || ''}</p>
<br/>
<p>Dr ${doctorName}</p>
<p>Emitido em: 0</p> <p>Emitido em: 0</p>
</div> </div>
`; `;
}; };
// Função que será chamada ao salvar
const handleSave = () => {
setLoading(true)
var myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", authHeader);
myHeaders.append("Content-Type", "application/json");
// Salva apenas o novo conteúdo do Tiptap (relatorioData.content)
const raw = JSON.stringify({
content: relatorioData.content,
// Você pode manter order_number ou removê-lo se não for editável
order_number: relatorioData.order_number || 'REL-2025-4386'
})
var requestOptions = {
method: 'PATCH',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?id=eq.${RelatorioID}`, requestOptions)
.then(response => response.text())
.then(result => {
console.log(result);
alert('Relatório atualizado com sucesso!');
setLoading(false)
// MANTIDO: Volta para a área de relatórios
navigate('/medico/relatorios')
})
.catch(error => {
console.log('error', error);
alert('Erro ao atualizar o relatório.');
setLoading(false)
});
}
// Busca os dados do Relatório e do Paciente
useEffect(() => { useEffect(() => {
const fetchReportData = async () => { const load = async () => {
var myHeaders = new Headers(); setLoading(true);
try {
const myHeaders = new Headers();
myHeaders.append("apikey", API_KEY); myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", authHeader); myHeaders.append("Authorization", authHeader);
var requestOptions = { const requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' };
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
let report;
let patient;
try {
const response = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?id=eq.${RelatorioID}`, requestOptions);
const result = await response.json();
if (result.length > 0) { // Pega relatório por id (supabase geralmente retorna array para ?id=eq.X)
report = result[0]; const resp = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?id=eq.${params.id}`, requestOptions);
const data = await resp.json();
const rep = Array.isArray(data) ? data[0] : data;
if (!rep) throw new Error('Relatório não encontrado');
// Busca nome do paciente setReport(rep);
const patientResult = await GetPatientByID(report.patient_id, authHeader);
if (patientResult.length > 0) {
patient = patientResult[0];
setPatientData(patient);
}
// Determina o conteúdo inicial // busca paciente
let initialContent = report.content || report.diagnosis || report.conclusion || ''; if (rep.patient_id) {
const p = await GetPatientByID(rep.patient_id, authHeader);
// Se o conteúdo estiver vazio, carrega o modelo do relatório completo setPatient(Array.isArray(p) ? p[0] : p);
if (!initialContent.trim()) {
initialContent = generateReportModel(report, patient);
}
setRelatorioData({
...report,
content: initialContent,
});
}
} catch (error) {
console.log('error', error);
} finally {
setLoading(false)
} }
// busca doctor se tiver created_by/requested_by id (tentamos fallback)
if (rep.created_by) {
try {
const d = await GetDoctorByID(rep.created_by, authHeader);
setDoctor(Array.isArray(d) ? d[0] : d);
} catch (e) {
// ignore
}
}
// content_html preferencial
let initial = rep.content_html || rep.content || rep.diagnosis || rep.conclusion || '';
if (!initial || initial.trim() === '') {
initial = generateTemplate(rep, patient || {}, doctor || {});
}
setHtml(initial);
} catch (err) {
console.error('Erro carregar relatório', err);
alert('Erro ao carregar relatório. Veja console.');
} finally {
setLoading(false);
}
};
load();
// eslint-disable-next-line
}, [params.id, authHeader]);
const handleSave = async () => {
setLoading(true);
try {
const myHeaders = new Headers();
myHeaders.append('apikey', API_KEY);
myHeaders.append('Authorization', authHeader);
myHeaders.append('Content-Type', 'application/json');
const body = JSON.stringify({ content_html: html });
// supabase: PATCH via query id=eq.<id>
const res = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?id=eq.${params.id}`, {
method: 'PATCH',
headers: myHeaders,
body
});
if (!res.ok) {
const txt = await res.text();
console.error('Erro PATCH', res.status, txt);
throw new Error('Erro na API');
}
alert('Relatório atualizado com sucesso!');
navigate('/medico/relatorios');
} catch (err) {
console.error(err);
alert('Erro ao salvar. Veja console.');
} finally {
setLoading(false);
} }
fetchReportData() };
}, [RelatorioID, authHeader])
// Função para atualizar o HTML do editor if (loading) return <div>Carregando...</div>;
const handleEditorChange = (newHtml) => {
setRelatorioData(prev => ({ ...prev, content: newHtml }))
}
if (loading) {
return <div>Carregando...</div>
}
return ( return (
<div className='container'> <div className='container'>
{/* MANTIDO: Título limpo */} <h3 className='mb-4'>Editar Relatório do Paciente: {patient?.full_name || '...'}</h3>
<h3 className='mb-4'>Editar Relatório do Paciente: {patientData?.full_name}</h3>
{/* MUDANÇA: Removidos todos os inputs de texto avulsos */}
{/* Campo do Tiptap Editor */}
<div className='mb-3'> <div className='mb-3'>
{/* MUDANÇA: Título ajustado */}
<h5 className='mb-2'>Conteúdo do Relatório</h5> <h5 className='mb-2'>Conteúdo do Relatório</h5>
<TiptapEditor <TiptapEditor content={html} onChange={(newHtml) => setHtml(newHtml)} />
content={relatorioData.content}
onChange={handleEditorChange}
/>
</div> </div>
<button className='btn btn-success' onClick={handleSave}>
Salvar Relatório
</button>
<div className='d-flex justify-content-center mt-4'>
<button className='btn btn-success' onClick={handleSave} disabled={loading}>
{loading ? 'Salvando...' : 'Salvar Relatório'}
</button>
</div>
</div> </div>
) );
} };
export default EditPageRelatorio;
export default EditPageRelatorio

View File

@ -1,44 +1,243 @@
import React, { useEffect, useState, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import API_KEY from '../components/utils/apiKeys';
import { useAuth } from '../components/utils/AuthProvider';
import TiptapEditor from './TiptapEditor';
import { GetAllPatients, GetPatientByID } from '../components/utils/Functions-Endpoints/Patient';
import { GetAllDoctors, GetDoctorByID } from '../components/utils/Functions-Endpoints/Doctor';
import './styleMedico/FormNovoRelatorio.css';
import '../PagesMedico/styleMedico/FormNovoRelatorio.css'
import API_KEY from '../components/utils/apiKeys'
import FormRelatorio from '../components/FormRelatorio'
import { useState } from 'react'
import { useAuth } from '../components/utils/AuthProvider'
const FormNovoRelatorio = () => { const FormNovoRelatorio = () => {
const [DictInfo, setDictInfo] = useState({}) const { getAuthorizationHeader } = useAuth();
const authHeader = getAuthorizationHeader();
const navigate = useNavigate();
const {getAuthorizationHeader} = useAuth() const [patients, setPatients] = useState([]);
let authHeader = getAuthorizationHeader() const [doctors, setDoctors] = useState([]);
const [loadingPatients, setLoadingPatients] = useState(true);
const [loadingDoctors, setLoadingDoctors] = useState(true);
const handleSave = (data) => { // formulário
console.log("Relatório salvo:", data); const [form, setForm] = useState({
patient_id: '',
patient_name: '',
patient_birth: '',
doctor_id: '',
doctor_name: '',
contentHtml: '',
});
var myHeaders = new Headers(); // campos de busca (texto)
myHeaders.append("apikey", API_KEY); const [patientQuery, setPatientQuery] = useState('');
myHeaders.append("Authorization", authHeader); const [doctorQuery, setDoctorQuery] = useState('');
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify({...data}); // dropdown control
const [showPatientDropdown, setShowPatientDropdown] = useState(false);
const [showDoctorDropdown, setShowDoctorDropdown] = useState(false);
var requestOptions = { const patientRef = useRef();
method: 'POST', const doctorRef = useRef();
headers: myHeaders,
body: raw, useEffect(() => {
redirect: 'follow' // carregar pacientes
let mounted = true;
const loadPatients = async () => {
setLoadingPatients(true);
try {
const list = await GetAllPatients(authHeader);
if (mounted && Array.isArray(list)) setPatients(list);
} catch (err) {
console.error('Erro GetAllPatients:', err);
} finally {
if (mounted) setLoadingPatients(false);
}
};
const loadDoctors = async () => {
setLoadingDoctors(true);
try {
const list = await GetAllDoctors(authHeader);
if (mounted && Array.isArray(list)) setDoctors(list);
} catch (err) {
console.error('Erro GetAllDoctors:', err);
} finally {
if (mounted) setLoadingDoctors(false);
}
};
loadPatients();
loadDoctors();
return () => { mounted = false; };
}, [authHeader]);
// fechar dropdowns quando clicar fora
useEffect(() => {
const handleClick = (e) => {
if (patientRef.current && !patientRef.current.contains(e.target)) setShowPatientDropdown(false);
if (doctorRef.current && !doctorRef.current.contains(e.target)) setShowDoctorDropdown(false);
};
document.addEventListener('click', handleClick);
return () => document.removeEventListener('click', handleClick);
}, []);
const generateTemplate = (patientName = '', birthDate = '', doctorName = '') => {
return `
<div>
<p style="text-align:center; font-weight:bold;">Clinica Rise up</p>
<p style="text-align:center;">Dr - CRM/SP 123456</p>
<p style="text-align:center;">Avenida - (79) 9 4444-4444</p>
<br/>
<p><strong>Paciente:</strong> ${patientName}</p>
<p><strong>Data de nascimento:</strong> ${birthDate}</p>
<p><strong>Data do exame:</strong> </p>
<p><strong>Exame:</strong> </p>
<br/>
<p><strong>Diagnóstico:</strong></p>
<p></p>
<br/>
<p><strong>Conclusão:</strong></p>
<p></p>
<br/>
<p>Dr ${doctorName}</p>
<p>Emitido em: 0</p>
</div>
`;
};
// escolher paciente (clicando na lista)
const choosePatient = async (patient) => {
setForm(prev => ({
...prev,
patient_id: patient.id,
patient_name: patient.full_name || '',
patient_birth: patient.birth_date || '',
contentHtml: generateTemplate(patient.full_name || '', patient.birth_date || '', form.doctor_name)
}));
setPatientQuery('');
setShowPatientDropdown(false);
};
const chooseDoctor = (doctor) => {
setForm(prev => ({
...prev,
doctor_id: doctor.id,
doctor_name: doctor.full_name || '',
contentHtml: generateTemplate(form.patient_name, form.patient_birth, doctor.full_name || '')
}));
setDoctorQuery('');
setShowDoctorDropdown(false);
};
// filtrar pela query (startsWith)
const filteredPatients = patientQuery
? patients.filter(p => (p.full_name || '').toLowerCase().startsWith(patientQuery.toLowerCase())).slice(0, 40)
: [];
const filteredDoctors = doctorQuery
? doctors.filter(d => (d.full_name || '').toLowerCase().startsWith(doctorQuery.toLowerCase())).slice(0, 40)
: [];
const handleEditorChange = (html) => setForm(prev => ({ ...prev, contentHtml: html }));
// salvar novo relatório
const handleSubmit = async (e) => {
e.preventDefault();
if (!form.patient_id) return alert('Selecione o paciente (clicando no item) antes de salvar.');
if (!form.doctor_id) return alert('Selecione o médico (clicando no item) antes de salvar.');
try {
const myHeaders = new Headers();
myHeaders.append('apikey', API_KEY);
myHeaders.append('Authorization', authHeader);
myHeaders.append('Content-Type', 'application/json');
const body = JSON.stringify({
patient_id: form.patient_id,
content: form.contentHtml,
content_html: form.contentHtml,
requested_by: form.doctor_name || '',
created_by: form.doctor_id || null,
status: 'draft'
});
const res = await fetch('https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports', {
method: 'POST',
headers: myHeaders,
body,
});
if (!res.ok) {
const txt = await res.text();
console.error('Erro POST criar relatório:', res.status, txt);
// mostra mensagem mais útil
return alert(`Erro ao criar relatório (ver console). Status ${res.status}`);
}
alert('Relatório criado com sucesso!');
navigate('/medico/relatorios');
} catch (err) {
console.error('Erro salvar relatório:', err);
alert('Erro ao salvar relatório. Veja console.');
}
};
return (
<div className="container">
<h3 className="mb-4">Criar Novo Relatório</h3>
<form onSubmit={handleSubmit} className="card p-4 mb-4">
<div className="row g-3 align-items-end">
<div className="col-md-6" ref={patientRef}>
<label className="form-label">Buscar paciente (digite para filtrar)</label>
<input
className="form-control"
placeholder="Comece a digitar (ex.: m para pacientes que começam com m)"
value={patientQuery}
onChange={(e) => { setPatientQuery(e.target.value); setShowPatientDropdown(true); }}
onFocus={() => setShowPatientDropdown(true)}
/>
{showPatientDropdown && patientQuery && (
<ul className="list-group position-absolute" style={{ zIndex: 50, maxHeight: 220, overflowY: 'auto', width: '45%' }}>
{filteredPatients.length > 0 ? filteredPatients.map(p => (
<li key={p.id} className="list-group-item list-group-item-action" onClick={() => choosePatient(p)}>
{p.full_name} {p.cpf ? `- ${p.cpf}` : ''}
</li>
)) : <li className="list-group-item">Nenhum paciente começando com "{patientQuery}"</li>}
</ul>
)}
<div className="form-text">Clique no paciente desejado para selecioná-lo e preencher o template.</div>
</div>
<div className="col-md-6" ref={doctorRef}>
<label className="form-label">Buscar médico (digite para filtrar)</label>
<input
className="form-control"
placeholder="Comece a digitar o nome do médico"
value={doctorQuery}
onChange={(e) => { setDoctorQuery(e.target.value); setShowDoctorDropdown(true); }}
onFocus={() => setShowDoctorDropdown(true)}
/>
{showDoctorDropdown && doctorQuery && (
<ul className="list-group position-absolute" style={{ zIndex: 50, maxHeight: 220, overflowY: 'auto', width: '45%', right: 0 }}>
{filteredDoctors.length > 0 ? filteredDoctors.map(d => (
<li key={d.id} className="list-group-item list-group-item-action" onClick={() => chooseDoctor(d)}>
{d.full_name} {d.crm ? `- CRM ${d.crm}` : ''}
</li>
)) : <li className="list-group-item">Nenhum médico começando com "{doctorQuery}"</li>}
</ul>
)}
<div className="form-text">Clique no médico desejado para selecioná-lo.</div>
</div>
<div className="col-12 text-end">
<button type="submit" className="btn btn-success">Salvar Relatório</button>
</div>
</div>
<hr className="my-3" />
<h5>Conteúdo do Relatório (edite tudo aqui)</h5>
<TiptapEditor content={form.contentHtml || generateTemplate(form.patient_name, form.patient_birth, form.doctor_name)} onChange={handleEditorChange} />
</form>
</div>
);
}; };
fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports", requestOptions) export default FormNovoRelatorio;
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
return (
<div>
<h3>Criar Novo Relatorio</h3>
<FormRelatorio DictInfo={DictInfo} setDictInfo={setDictInfo} onSave={handleSave} />
</div>
)
}
export default FormNovoRelatorio

View File

@ -1,74 +1,55 @@
import React from 'react'; import React, { useEffect } from 'react';
import { useEditor, EditorContent } from '@tiptap/react'; import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit'; import StarterKit from '@tiptap/starter-kit';
import Link from '@tiptap/extension-link'; import Link from '@tiptap/extension-link';
// Componente da barra de menu (Menu Bar)
// MenuBar simples
const MenuBar = ({ editor }) => { const MenuBar = ({ editor }) => {
if (!editor) { if (!editor) return null;
return null; const btn = { marginRight: '6px', padding: '4px 8px', cursor: 'pointer', border: '1px solid #ccc', borderRadius: 4 };
}
// Estilos simples para os botões. Você pode e deve estilizar melhor com CSS/Bootstrap.
const buttonStyle = {
marginRight: '4px',
padding: '4px 8px',
cursor: 'pointer',
border: '1px solid #ccc',
borderRadius: '4px',
backgroundColor: editor.isActive('bold') || editor.isActive('italic') ? '#ddd' : 'white',
};
return ( return (
<div style={{ padding: '8px', borderBottom: '1px solid #ccc', display: 'flex', flexWrap: 'wrap' }}> <div style={{ padding: 8, borderBottom: '1px solid #e6e6e6', display: 'flex', flexWrap: 'wrap' }}>
<button <button style={{ ...btn, fontWeight: 'bold' }} onClick={() => editor.chain().focus().toggleBold().run()}>B</button>
onClick={() => editor.chain().focus().toggleBold().run()} <button style={{ ...btn }} onClick={() => editor.chain().focus().toggleItalic().run()}>I</button>
disabled={!editor.can().chain().focus().toggleBold().run()} <button style={{ ...btn }} onClick={() => editor.chain().focus().toggleBulletList().run()}>Lista</button>
style={{ ...buttonStyle, fontWeight: 'bold' }} <button style={{ ...btn }} onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}>Título 2</button>
> <button style={{ ...btn }} onClick={() => { const url = prompt('URL'); if (url) editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run(); }}>Link</button>
B
</button>
<button
onClick={() => editor.chain().focus().toggleItalic().run()}
disabled={!editor.can().chain().focus().toggleItalic().run()}
style={{ ...buttonStyle, fontStyle: 'italic' }}
>
I
</button>
<button
onClick={() => editor.chain().focus().toggleBulletList().run()}
style={{ ...buttonStyle, backgroundColor: editor.isActive('bulletList') ? '#ddd' : 'white' }}
>
Lista
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
style={{ ...buttonStyle, backgroundColor: editor.isActive('heading', { level: 2 }) ? '#ddd' : 'white' }}
>
Título 2
</button>
{/* Adicione mais botões conforme a necessidade (link, código, etc.) */}
</div> </div>
); );
}; };
// Componente principal do Editor
const TiptapEditor = ({ content, onChange }) => { const TiptapEditor = ({ content, onChange }) => {
const editor = useEditor({ const editor = useEditor({
extensions: [ extensions: [
StarterKit.configure({ StarterKit.configure({ hardBreak: false }),
// Desativa 'hardBreak' e 'blockquote' se não forem necessários para simplificar Link,
hardBreak: false,
}),
Link, // Adiciona suporte para links
], ],
content: content || '<p>Inicie o relatório aqui...</p>', content: content || '<p>Inicie o relatório aqui...</p>',
onUpdate: ({ editor }) => { onUpdate: ({ editor }) => {
// Quando o conteúdo muda, chama a função onChange com o HTML onChange && onChange(editor.getHTML());
onChange(editor.getHTML());
}, },
}); });
// Se o pai mudar 'content', atualizamos o editor
useEffect(() => {
if (!editor) return;
// Só setContent se for diferente para evitar perda de edição
try {
const current = editor.getHTML();
if ((content || '').trim() && content !== current) {
editor.commands.setContent(content);
}
} catch (e) {
// ignore
}
}, [editor, content]);
return ( return (
<div className='tiptap-editor-container' style={{ border: '1px solid #ccc', borderRadius: '4px' }}> <div className='tiptap-editor-container' style={{ border: '1px solid #ddd', borderRadius: 6, overflow: 'hidden' }}>
<MenuBar editor={editor} /> <MenuBar editor={editor} />
<EditorContent editor={editor} style={{ minHeight: '300px', padding: '10px' }} /> <EditorContent editor={editor} style={{ minHeight: 360, padding: 12, background: 'white' }} />
</div> </div>
); );
}; };
export default TiptapEditor; export default TiptapEditor;

View File

@ -1,26 +1,25 @@
import API_KEY from "../apiKeys"; import API_KEY from '../apiKeys';
const GetDoctorByID = async (ID,authHeader) => {
console.log(authHeader, 'mostrando autorização dentro da função')
const GetDoctorByID = async (ID, authHeader) => {
var myHeaders = new Headers(); var myHeaders = new Headers();
myHeaders.append('apikey', API_KEY) myHeaders.append('apikey', API_KEY);
myHeaders.append('Authorization', authHeader) if (authHeader) myHeaders.append('Authorization', authHeader);
var requestOptions = { const requestOptions = { method: 'GET', redirect: 'follow', headers: myHeaders };
method: 'GET', const res = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors?id=eq.${ID}`, requestOptions);
redirect: 'follow', const DictMedico = await res.json();
headers:myHeaders return DictMedico;
}; };
const GetAllDoctors = async (authHeader) => {
var myHeaders = new Headers();
myHeaders.append('apikey', API_KEY);
if (authHeader) myHeaders.append('Authorization', authHeader);
const result = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors?id=eq.${ID}`, requestOptions) const requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' };
const DictMedico = await result.json() const res = await fetch('https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors?select=id,full_name,crm&limit=500', requestOptions);
return DictMedico const DictMedicos = await res.json();
return DictMedicos;
};
} export { GetDoctorByID, GetAllDoctors };
export {GetDoctorByID}