diff --git a/package-lock.json b/package-lock.json index b9f9b87..44324ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2630,9 +2630,9 @@ } }, "node_modules/@ckeditor/ckeditor5-alignment/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -3143,9 +3143,9 @@ } }, "node_modules/@ckeditor/ckeditor5-autosave/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -4125,9 +4125,9 @@ } }, "node_modules/@ckeditor/ckeditor5-bookmark/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -7240,9 +7240,9 @@ } }, "node_modules/@ckeditor/ckeditor5-clipboard/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -7757,9 +7757,9 @@ } }, "node_modules/@ckeditor/ckeditor5-code-block/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -8283,9 +8283,9 @@ } }, "node_modules/@ckeditor/ckeditor5-editor-balloon/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -8799,9 +8799,9 @@ } }, "node_modules/@ckeditor/ckeditor5-editor-decoupled/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -8902,9 +8902,9 @@ } }, "node_modules/@ckeditor/ckeditor5-editor-inline/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -9005,9 +9005,9 @@ } }, "node_modules/@ckeditor/ckeditor5-editor-multi-root/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -9124,9 +9124,9 @@ } }, "node_modules/@ckeditor/ckeditor5-emoji/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -9234,9 +9234,9 @@ } }, "node_modules/@ckeditor/ckeditor5-enter/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -9749,9 +9749,9 @@ } }, "node_modules/@ckeditor/ckeditor5-find-and-replace/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -9852,9 +9852,9 @@ } }, "node_modules/@ckeditor/ckeditor5-font/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -9971,9 +9971,9 @@ } }, "node_modules/@ckeditor/ckeditor5-fullscreen/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -10485,9 +10485,9 @@ } }, "node_modules/@ckeditor/ckeditor5-highlight/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -10588,9 +10588,9 @@ } }, "node_modules/@ckeditor/ckeditor5-horizontal-line/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -10691,9 +10691,9 @@ } }, "node_modules/@ckeditor/ckeditor5-html-embed/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -10901,9 +10901,9 @@ } }, "node_modules/@ckeditor/ckeditor5-html-support/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -11847,9 +11847,9 @@ } }, "node_modules/@ckeditor/ckeditor5-language/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -12789,9 +12789,9 @@ } }, "node_modules/@ckeditor/ckeditor5-markdown-gfm/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -13318,9 +13318,9 @@ } }, "node_modules/@ckeditor/ckeditor5-mention/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -13420,9 +13420,9 @@ } }, "node_modules/@ckeditor/ckeditor5-minimap/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -13523,9 +13523,9 @@ } }, "node_modules/@ckeditor/ckeditor5-page-break/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -14061,9 +14061,9 @@ } }, "node_modules/@ckeditor/ckeditor5-remove-format/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -14164,9 +14164,9 @@ } }, "node_modules/@ckeditor/ckeditor5-restricted-editing/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -14266,9 +14266,9 @@ } }, "node_modules/@ckeditor/ckeditor5-select-all/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -14368,9 +14368,9 @@ } }, "node_modules/@ckeditor/ckeditor5-show-blocks/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -14471,9 +14471,9 @@ } }, "node_modules/@ckeditor/ckeditor5-source-editing/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -14587,9 +14587,9 @@ } }, "node_modules/@ckeditor/ckeditor5-special-characters/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -14743,9 +14743,9 @@ } }, "node_modules/@ckeditor/ckeditor5-style/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -15255,9 +15255,9 @@ } }, "node_modules/@ckeditor/ckeditor5-theme-lark/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -15383,9 +15383,9 @@ } }, "node_modules/@ckeditor/ckeditor5-undo/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -15482,9 +15482,9 @@ } }, "node_modules/@ckeditor/ckeditor5-upload/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -15593,9 +15593,9 @@ } }, "node_modules/@ckeditor/ckeditor5-watchdog/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -15711,9 +15711,9 @@ } }, "node_modules/@ckeditor/ckeditor5-widget/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -15813,9 +15813,9 @@ } }, "node_modules/@ckeditor/ckeditor5-word-count/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -19567,9 +19567,9 @@ } }, "node_modules/@types/react-dom": { - "version": "19.2.2", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", - "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", "peer": true, "peerDependencies": { @@ -22017,9 +22017,9 @@ } }, "node_modules/ckeditor5/node_modules/color-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz", - "integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "peer": true, "engines": { @@ -28911,9 +28911,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "peer": true, "dependencies": { @@ -31881,6 +31881,23 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", diff --git a/src/PagesAdm/gestao.css b/src/PagesAdm/gestao.css index 5991041..9951eae 100644 --- a/src/PagesAdm/gestao.css +++ b/src/PagesAdm/gestao.css @@ -1,4 +1,3 @@ - .dashboard-container { padding: 2rem; font-family: 'Arial', sans-serif; @@ -6,7 +5,6 @@ min-height: 100vh; } - .dashboard-header { display: flex; justify-content: space-between; @@ -34,143 +32,133 @@ border: none; border-radius: 8px; font-size: 1rem; + font-weight: 600; cursor: pointer; - transition: background-color 0.3s, transform 0.25s ease, box-shadow 0.25s ease; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(30, 58, 138, 0.3); } .new-user-btn:hover { background-color: #162d6b; transform: translateY(-2px); - box-shadow: 0px 4px 12px rgba(30, 58, 138, 0.3); + box-shadow: 0 4px 12px rgba(30, 58, 138, 0.4); } - .filters-container { background: #fff; border-radius: 12px; - padding: 1.5rem; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + padding: 1.2rem; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); margin-bottom: 2rem; - transition: transform 0.2s ease, box-shadow 0.2s ease; -} - -.filters-container:hover { - transform: translateY(-3px); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); } .filters-title { - font-size: 18px; + font-size: 16px; font-weight: bold; margin-bottom: 0.3rem; color: #333; } .filters-subtitle { - font-size: 0.9rem; + font-size: 0.85rem; color: #666; margin-bottom: 1rem; } .filters-content { display: flex; - gap: 1rem; + gap: 0.8rem; align-items: center; } .filters-input { flex: 1; - padding: 0.6rem 1rem; + padding: 0.5rem 0.8rem; border: 1px solid #d1d5db; - border-radius: 8px; - font-size: 0.95rem; + border-radius: 6px; + font-size: 0.9rem; color: #333; - transition: border-color 0.2s, box-shadow 0.2s; + min-width: 200px; + transition: all 0.2s ease; } .filters-input:focus { border-color: #1e3a8a; - box-shadow: 0px 0px 0px 3px rgba(30, 58, 138, 0.2); + box-shadow: 0 0 0 2px rgba(30, 58, 138, 0.1); outline: none; } .filters-select { - padding: 0.6rem 1rem; + padding: 0.5rem 0.8rem; border: 1px solid #d1d5db; - border-radius: 8px; - font-size: 0.95rem; + border-radius: 6px; + font-size: 0.9rem; background: #fff; color: #333; cursor: pointer; - transition: border-color 0.2s, box-shadow 0.2s; + min-width: 140px; + transition: all 0.2s ease; } .filters-select:focus { border-color: #1e3a8a; - box-shadow: 0px 0px 0px 3px rgba(30, 58, 138, 0.2); + box-shadow: 0 0 0 2px rgba(30, 58, 138, 0.1); outline: none; } - .cards-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 1.5rem; + gap: 1.2rem; margin-bottom: 2rem; } .card { background-color: white; - padding: 1.5rem; - border-radius: 12px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + padding: 1.2rem; + border-radius: 10px; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); border: 1px solid transparent; - transition: transform 0.25s ease, box-shadow 0.25s ease, border 0.25s ease, background 0.25s ease; + transition: all 0.25s ease; cursor: pointer; } .highlight:hover { - transform: translateY(-6px); - box-shadow: 0 8px 20px rgba(30, 58, 138, 0.2); + transform: translateY(-4px); + box-shadow: 0 6px 16px rgba(30, 58, 138, 0.2); background: #f8faff; border: 1px solid #1e3a8a33; } .card-label { - font-size: 0.9rem; + font-size: 0.85rem; color: #999; margin-bottom: 0.5rem; } .card-value { - font-size: 1.8rem; + font-size: 1.6rem; font-weight: bold; margin: 0; color: #333; } .card-extra { - font-size: 0.85rem; + font-size: 0.8rem; color: #666; } .card-extra.positive { color: #1e3a8a; + font-weight: 600; } - .user-table-container { background: #fff; border-radius: 12px; - padding: 1.5rem; - box-shadow: 0 4px 6px rgba(0,0,0,0.1); + padding: 1.2rem; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); margin-top: 2rem; - transition: transform 0.25s ease, box-shadow 0.25s ease; -} - -.user-table-container:hover { - transform: translateY(-4px); - box-shadow: 0 6px 14px rgba(0,0,0,0.15); } .user-table-container h2 { @@ -193,7 +181,7 @@ .user-table th, .user-table td { - padding: 12px 15px; + padding: 10px 12px; text-align: left; border-bottom: 1px solid #e0e0e0; } @@ -202,10 +190,11 @@ background-color: #f3f4f6; color: #333; font-weight: 600; + font-size: 0.9rem; } .user-table tr { - transition: background-color 0.25s ease; + transition: background-color 0.2s ease; } .user-table tr:hover { @@ -214,44 +203,115 @@ .profile-badge { background-color: #1e3a8a; - color: #f7f7f7; - padding: 3px 8px; - border-radius: 8px; - font-size: 0.85rem; + color: white; + padding: 4px 10px; + border-radius: 6px; + font-size: 0.8rem; + font-weight: 500; display: inline-block; } .status-badge { - padding: 3px 8px; - border-radius: 8px; - font-size: 0.85rem; + padding: 4px 10px; + border-radius: 6px; + font-size: 0.8rem; color: #fff; + font-weight: 500; display: inline-block; text-transform: capitalize; } .status-badge.ativo { - background-color: #28a745; + background-color: #1e3a8a; } .status-badge.inativo { - background-color: #dc3545; + background-color: #6c757d; } .actions { display: flex; - gap: 10px; + gap: 8px; + flex-wrap: wrap; } -.action-icon { +.action-btn { + border: none; + padding: 6px 12px; + font-size: 0.8rem; + font-weight: 500; cursor: pointer; - color: #555; - transition: color 0.2s, transform 0.2s; + transition: all 0.2s ease; + border-radius: 4px; + display: inline-flex; + align-items: center; + gap: 4px; } -.action-icon:hover { - color: #1e3a8a; - transform: scale(1.2); +.action-btn.detalhes { + background-color: #e6f2ff; + color: #004085; + border: 1px solid #b8d4ff; +} + +.action-btn.detalhes:hover { + background-color: #cce4ff; + transform: translateY(-1px); +} + +.action-btn.editar { + background-color: #fff3cd; + color: #856405; + border: 1px solid #ffeaa7; +} + +.action-btn.editar:hover { + background-color: #ffeaa7; + transform: translateY(-1px); +} + +.action-btn.excluir { + background-color: #f8d7da; + color: #721c24; + border: 1px solid #f1b0b7; +} + +.action-btn.excluir:hover { + background-color: #f1b0b7; + transform: translateY(-1px); +} + +.save-btn { + background-color: #1e3a8a; + color: white; + border: none; + padding: 8px 16px; + border-radius: 6px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; +} + +.save-btn:hover { + background-color: #162d6b; + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(30, 58, 138, 0.3); +} + +.edit-btn { + background-color: #fff3cd; + color: #856405; + border: 1px solid #ffeaa7; + padding: 8px 16px; + border-radius: 6px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; +} + +.edit-btn:hover { + background-color: #ffeaa7; + transform: translateY(-1px); } html[data-bs-theme="dark"] .dashboard-container { @@ -266,18 +326,17 @@ html[data-bs-theme="dark"] .dashboard-subtitle { } html[data-bs-theme="dark"] .new-user-btn { - background-color: #2563eb; - color: #fff; + background-color: #1e3a8a; } html[data-bs-theme="dark"] .new-user-btn:hover { - background-color: #1e40af; + background-color: #162d6b; } html[data-bs-theme="dark"] .filters-container, html[data-bs-theme="dark"] .user-table-container { background: #1a1a1a; - box-shadow: 0 4px 6px rgba(0,0,0,0.4); + box-shadow: 0 2px 8px rgba(0,0,0,0.4); } html[data-bs-theme="dark"] .filters-title, @@ -299,19 +358,19 @@ html[data-bs-theme="dark"] .filters-select { html[data-bs-theme="dark"] .filters-input:focus, html[data-bs-theme="dark"] .filters-select:focus { - border-color: #2563eb; - box-shadow: 0px 0px 0px 3px rgba(37, 99, 235, 0.2); + border-color: #1e3a8a; + box-shadow: 0 0 0 2px rgba(30, 58, 138, 0.2); } html[data-bs-theme="dark"] .cards-container .card { background-color: #181818; color: #e0e0e0; - box-shadow: 0 4px 6px rgba(0,0,0,0.4); + box-shadow: 0 2px 6px rgba(0,0,0,0.4); } html[data-bs-theme="dark"] .highlight:hover { - background: #232a3a; - border: 1px solid #2563eb33; + background: #1a1f2e; + border: 1px solid #1e3a8a33; } html[data-bs-theme="dark"] .card-label { @@ -327,7 +386,7 @@ html[data-bs-theme="dark"] .card-extra { } html[data-bs-theme="dark"] .card-extra.positive { - color: #2563eb; + color: #1e3a8a; } html[data-bs-theme="dark"] .user-table th { @@ -341,26 +400,39 @@ html[data-bs-theme="dark"] .user-table td { } html[data-bs-theme="dark"] .user-table tr:hover { - background-color: #232a3a; + background-color: #1a1f2e; } html[data-bs-theme="dark"] .profile-badge { - background-color: #2563eb; - color: #fff; + background-color: #1e3a8a; } -html[data-bs-theme="dark"] .status-badge.ativo { - background-color: #28a745; +html[data-bs-theme="dark"] .action-btn.detalhes { + background-color: #e6f2ff; + color: #004085; + border: 1px solid #b8d4ff; } -html[data-bs-theme="dark"] .status-badge.inativo { - background-color: #dc3545; +html[data-bs-theme="dark"] .action-btn.detalhes:hover { + background-color: #cce4ff; } -html[data-bs-theme="dark"] .action-icon { - color: #bdbdbd; +html[data-bs-theme="dark"] .action-btn.editar { + background-color: #fff3cd; + color: #856405; + border: 1px solid #ffeaa7; } -html[data-bs-theme="dark"] .action-icon:hover { - color: #2563eb; +html[data-bs-theme="dark"] .action-btn.editar:hover { + background-color: #ffeaa7; +} + +html[data-bs-theme="dark"] .action-btn.excluir { + background-color: #f8d7da; + color: #721c24; + border: 1px solid #f1b0b7; +} + +html[data-bs-theme="dark"] .action-btn.excluir:hover { + background-color: #f1b0b7; } \ No newline at end of file diff --git a/src/PagesAdm/gestao.jsx b/src/PagesAdm/gestao.jsx index 7d982b9..a5ecd88 100644 --- a/src/PagesAdm/gestao.jsx +++ b/src/PagesAdm/gestao.jsx @@ -1,14 +1,9 @@ - import React from "react"; import "./gestao.css"; -import { FaEdit, FaTrash } from "react-icons/fa"; - function UserDashboard() { return ( - -
- +

Gestão de Usuários

@@ -91,8 +86,9 @@ function UserDashboard() { Ativo 20/12/2024, 08:30 - - + + + @@ -103,8 +99,9 @@ function UserDashboard() { Ativo 19/12/2024, 14:20 - - + + + @@ -115,8 +112,9 @@ function UserDashboard() { Ativo 20/12/2024, 07:45 - - + + + @@ -127,8 +125,9 @@ function UserDashboard() { Inativo 15/12/2024, 16:30 - - + + + @@ -138,5 +137,4 @@ function UserDashboard() { ); } - export default UserDashboard; \ No newline at end of file diff --git a/src/PagesMedico/DoctorAgendamentoManager.jsx b/src/PagesMedico/DoctorAgendamentoManager.jsx index 34eb294..d89a68f 100644 --- a/src/PagesMedico/DoctorAgendamentoManager.jsx +++ b/src/PagesMedico/DoctorAgendamentoManager.jsx @@ -1,22 +1,14 @@ -import React, { useState, useMemo, useEffect, useCallback } from "react"; -import { useNavigate } from "react-router-dom"; -import API_KEY from "../components/utils/apiKeys.js"; -import AgendamentoCadastroManager from "../pages/AgendamentoCadastroManager.jsx"; -// Removidos imports não utilizados no novo fluxo -import { GetAllDoctors } from "../components/utils/Functions-Endpoints/Doctor.js"; -import { useAuth } from "../components/utils/AuthProvider.js"; -import dayjs from "dayjs"; -import "dayjs/locale/pt-br"; -import isBetween from "dayjs/plugin/isBetween"; -import localeData from "dayjs/plugin/localeData"; -import { - Search, - ChevronLeft, - ChevronRight, - Edit, - Trash2, - CheckCircle, -} from "lucide-react"; +import React, { useState, useMemo, useEffect, useCallback } from 'react'; +import { useNavigate } from 'react-router-dom'; +import API_KEY from '../components/utils/apiKeys.js'; +import AgendamentoCadastroManager from '../pages/AgendamentoCadastroManager.jsx'; +import { GetAllDoctors } from '../components/utils/Functions-Endpoints/Doctor.js'; +import { useAuth } from '../components/utils/AuthProvider.js'; +import dayjs from 'dayjs'; +import 'dayjs/locale/pt-br'; +import isBetween from 'dayjs/plugin/isBetween'; +import localeData from 'dayjs/plugin/localeData'; +import { Search, ChevronLeft, ChevronRight, Edit, Trash2, CheckCircle } from 'lucide-react'; import "../pages/style/Agendamento.css"; import "../pages/style/FilaEspera.css"; import Spinner from "../components/Spinner.jsx"; @@ -30,8 +22,8 @@ const Agendamento = () => { const { getAuthorizationHeader, user } = useAuth(); const authHeader = getAuthorizationHeader(); - // ID do médico que você quer visualizar - const ID_MEDICO_ESPECIFICO = "078d2a67-b4c1-43c8-ae32-c1e75bb5b3df"; + + const ID_MEDICO_ESPECIFICO = "078d2a67-b4c1-43c8-ae32-c1e75bb5b3df"; const [listaTodosAgendamentos, setListaTodosAgendamentos] = useState([]); const [selectedID, setSelectedId] = useState("0"); @@ -63,21 +55,17 @@ const Agendamento = () => { year: currentDate.year(), }); - // ✨ ALTERAÇÃO PRINCIPAL: A busca agora filtra pelo ID do médico direto na API - const fetchAppointments = useCallback(async () => { - if (!authHeader) return; - setShowSpinner(true); - const myHeaders = new Headers(); - myHeaders.append("Authorization", authHeader); - myHeaders.append("apikey", API_KEY); - const requestOptions = { - method: "GET", - headers: myHeaders, - redirect: "follow", - }; - // A URL agora contém o filtro para o ID do médico específico - const apiUrl = `https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?doctor_id=eq.${ID_MEDICO_ESPECIFICO}&select=*`; + const fetchAppointments = useCallback(async () => { + if (!authHeader) return; + setShowSpinner(true); + const myHeaders = new Headers(); + myHeaders.append("Authorization", authHeader); + myHeaders.append("apikey", API_KEY); + const requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; + + + const apiUrl = `https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?doctor_id=eq.${ID_MEDICO_ESPECIFICO}&select=*`; try { const res = await fetch(apiUrl, requestOptions); @@ -163,36 +151,33 @@ const Agendamento = () => { [updateAppointmentStatus] ); - useEffect(() => { - if (authHeader) { - fetchAppointments(); - // A busca de todos os médicos pode continuar caso a secretária precise ver a lista - if (user?.role !== "doctor") { - GetAllDoctors(authHeader).then((docs) => { - if (docs) { - setListaDeMedicos( - docs.map((d) => ({ nomeMedico: d.full_name, idMedico: d.id })) - ); - } - }); - } - } - }, [authHeader, fetchAppointments, user?.role]); + useEffect(() => { + if(authHeader) { + fetchAppointments(); + + if (user?.role !== 'doctor') { + GetAllDoctors(authHeader).then(docs => { + if (docs) { + setListaDeMedicos(docs.map(d => ({ nomeMedico: d.full_name, idMedico: d.id }))); + } + }); + } + } + }, [authHeader, fetchAppointments, user?.role]); - useEffect(() => { - const processData = async () => { - // Como os dados já vêm filtrados da API, não precisamos mais da verificação de 'user' aqui - if (!listaTodosAgendamentos.length) { - setAgendamentosOrganizados({}); - setFilaEsperaData([]); - return; - } + useEffect(() => { + const processData = async () => { + + if (!listaTodosAgendamentos.length) { + setAgendamentosOrganizados({}); + setFilaEsperaData([]); + return; + } setShowSpinner(true); - // ✨ SIMPLIFICAÇÃO: Não é mais necessário filtrar por `user.role`, - // pois a API já retornou apenas os agendamentos do médico desejado. - const appointmentsToShow = listaTodosAgendamentos; + + const appointmentsToShow = listaTodosAgendamentos; const patientIdsToFetch = new Set(); const doctorIdsToFetch = new Set(); @@ -208,19 +193,16 @@ const Agendamento = () => { const fetchPromises = []; - if (patientIdsToFetch.size > 0) { - const query = `id=in.(${Array.from(patientIdsToFetch).join(",")})`; - fetchPromises.push( - fetch( - `https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients?${query}&select=*`, - { - headers: { apikey: API_KEY, Authorization: authHeader }, + if (patientIdsToFetch.size > 0) { + const query = `id=in.(${Array.from(patientIdsToFetch).join(',')})`; + fetchPromises.push( + fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients?${query}&select=*`, { + headers: { apikey: API_KEY, Authorization: authHeader } + }).then(res => res.json()) + ); + } else { + fetchPromises.push(Promise.resolve(null)); } - ).then((res) => res.json()) - ); - } else { - fetchPromises.push(Promise.resolve(null)); // Mantém a ordem do Promise.all - } if (doctorIdsToFetch.size > 0) { const query = `id=in.(${Array.from(doctorIdsToFetch).join(",")})`; @@ -289,10 +271,10 @@ const Agendamento = () => { setShowSpinner(false); }; - processData(); - }, [listaTodosAgendamentos, authHeader]); // Removido 'user' das dependências pois não é mais usado aqui + processData(); + }, [listaTodosAgendamentos, authHeader]); + - // O restante do código permanece o mesmo... const handleEditConsulta = (agendamento) => { setAgendamentoParaEdicao(agendamento); @@ -323,59 +305,28 @@ const Agendamento = () => { return grid; }; - const dateGrid = useMemo(() => generateDateGrid(), [currentDate]); - const weekDays = ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"]; - const handleDateClick = (day) => setSelectedDay(day); - const DeleteModal = () => ( -
-
-
-
-
Confirmação de Cancelamento
- -
-
-

Qual o motivo do cancelamento? (Opcional)

- -
-
- - {/* ✨ Botão sempre ativo ✨ */} - -
+ const dateGrid = useMemo(() => generateDateGrid(), [currentDate]); + const weekDays = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb']; + const handleDateClick = (day) => setSelectedDay(day); +const DeleteModal = () => ( +
+
+
+
+
Confirmação de Cancelamento
+
+
+

Qual o motivo do cancelamento?

+ +
+
+ + +
+
-
); @@ -458,561 +409,320 @@ const Agendamento = () => { setSelectedDay(newDate); }; - return ( -
-

Agendar nova consulta

- {!PageNovaConsulta ? ( -
- {user?.role !== "doctor" && ( -
-
-
-
-
- handleSearchMedicos(e.target.value)} - /> -
-
- {searchTermDoctor && FiltredTodosMedicos.length > 0 && ( -
- {FiltredTodosMedicos.map((medico) => ( -
{ - setSearchTermDoctor(medico.nomeMedico); - setFiltredTodosMedicos([]); - setMedicoFiltrado({ id: medico.idMedico }); - }} - > -

{medico.nomeMedico}

-
- ))} -
- )} -
-
+ return ( +
+

Agendar nova consulta

+
+ + +
- )} -
-
- - -
-
- - - -
-
-
- {!FiladeEspera ? ( -
-
-
- {selectedDay.format("MMM")} - {selectedDay.format("DD")} -
-
-

{selectedDay.format("dddd")}

-

{selectedDay.format("D [de] MMMM [de] YYYY")}

-
-
-

Consultas para {selectedDay.format("DD/MM")}

- {showSpinner ? ( - - ) : DictAgendamentosOrganizados[ - selectedDay.format("YYYY-MM-DD") - ]?.filter( - (app) => - MedicoFiltrado.id === "vazio" || - app.doctor_id === MedicoFiltrado.id - ).length > 0 ? ( - DictAgendamentosOrganizados[ - selectedDay.format("YYYY-MM-DD") - ] - .filter( - (app) => - MedicoFiltrado.id === "vazio" || - app.doctor_id === MedicoFiltrado.id - ) - .map((app) => ( -
-
- {dayjs(app.scheduled_at).format("HH:mm")} -
-
- {app.paciente_nome} - Dr(a). {app.medico_nome} -
-
- {app.status === "cancelled" ? ( - - ) : ( - - )} - {app.status !== "cancelled" && ( - - )} -
-
- )) - ) : ( -
-

Nenhuma consulta agendada.

-
- )} -
-
-
-
-
- Realizado -
-
- Confirmado -
-
- Agendado -
-
- Cancelado -
-
-
-
-

{currentDate.format("MMMM [de] YYYY")}

-
- - - -
-
-
- - - -
-
-
- {weekDays.map((day) => ( -
- {day} -
- ))} - {dateGrid.map((day, index) => { - const dayString = day.format("YYYY-MM-DD"); - const appointmentsOnDay = - DictAgendamentosOrganizados[dayString] || []; - const filteredAppointments = appointmentsOnDay.filter( - (app) => - MedicoFiltrado.id === "vazio" || - app.doctor_id === MedicoFiltrado.id - ); - const cellClasses = `day-cell ${ - day.isSame(currentDate, "month") - ? "current-month" - : "other-month" - } ${day.isSame(dayjs(), "day") ? "today" : ""} ${ - day.isSame(selectedDay, "day") ? "selected" : "" - }`; - return ( -
handleDateClick(day)} - > - {day.format("D")} - {filteredAppointments.length > 0 && ( -
- {filteredAppointments.length} -
- )} -
- ); - })} -
-
-
- ) : ( -
-
-
-
-
-

Fila de Espera

-
-
+ {!PageNovaConsulta ? ( +
+ {user?.role !== 'doctor' && (
-
- {" "} - Filtros -
-
- - setWaitlistSearch(e.target.value) - } - /> - - Digite o nome do paciente, CPF ou nome do médico - -
-
-
- - Ordenar por: - - -
-
-
-
- {filaEsperaFiltrada.length} DE{" "} - {filaEsperaData.length} SOLICITAÇÕES ENCONTRADAS -
-
-
-
- - - - - - - - - - - - {filaEsperaPaginada.length > 0 ? ( - filaEsperaPaginada.map((item, index) => ( - - - - - - - - )) - ) : ( - - - - )} - -
Nome do PacienteCPFMédico SolicitadoData da SolicitaçãoAções
{item?.Infos?.paciente_nome}{item?.Infos?.paciente_cpf}{item?.Infos?.medico_nome} - {dayjs( - item.agendamento.scheduled_at - ).format("DD/MM/YYYY")} - - -
-
- {showSpinner ? ( - - ) : ( - <> - -

- Nenhuma solicitação encontrada. -

- - )} +
+ + Filtrar por Médico +
+
+ handleSearchMedicos(e.target.value)} + /> + Buscar médico para filtrar consultas + + {searchTermDoctor && FiltredTodosMedicos.length > 0 && ( +
+ {FiltredTodosMedicos.map((medico) => ( + + ))}
-
- {filaEsperaFiltrada.length > 0 && ( -
-
- - Itens por página: - - -
-
- - Página {waitPage} de {waitTotalPages} • - Mostrando {waitIndiceInicial + 1}- - {Math.min( - waitIndiceFinal, - filaEsperaFiltrada.length - )}{" "} - de {filaEsperaFiltrada.length} - - -
+ )}
- )} + + {MedicoFiltrado.id !== "vazio" && ( +
+ + + {searchTermDoctor} + + +
+ )}
-
+ )} +
+ +
-
-
-
+
+ {!FiladeEspera ? ( +
+
+
{selectedDay.format('MMM')}{selectedDay.format('DD')}
+

{selectedDay.format('dddd')}

{selectedDay.format('D [de] MMMM [de] YYYY')}

+
+

Consultas para {selectedDay.format('DD/MM')}

+ {showSpinner ? : (DictAgendamentosOrganizados[selectedDay.format('YYYY-MM-DD')]?.filter(app => MedicoFiltrado.id === "vazio" || app.doctor_id === MedicoFiltrado.id).length > 0) ? ( + DictAgendamentosOrganizados[selectedDay.format('YYYY-MM-DD')] + .filter(app => MedicoFiltrado.id === "vazio" || app.doctor_id === MedicoFiltrado.id) + .map(app => ( +
+
{dayjs(app.scheduled_at).format('HH:mm')}
+
{app.paciente_nome}Dr(a). {app.medico_nome}
+
+ {app.status === 'cancelled' ? ( + + ) : ( + + )} + {app.status !== 'cancelled' && ( + + )} +
+
+ )) + ) : (

Nenhuma consulta agendada.

)} +
+
+
+
+
Realizado
+
Confirmado
+
Agendado
+
Cancelado
+
+
+
+

{currentDate.format('MMMM [de] YYYY')}

+
+ + + +
+
+
+ + + +
+
+
+ {weekDays.map(day =>
{day}
)} + {dateGrid.map((day, index) => { + const dayString = day.format('YYYY-MM-DD'); + const appointmentsOnDay = DictAgendamentosOrganizados[dayString] || []; + const filteredAppointments = appointmentsOnDay.filter(app => MedicoFiltrado.id === "vazio" || app.doctor_id === MedicoFiltrado.id); + const cellClasses = `day-cell ${day.isSame(currentDate, 'month') ? 'current-month' : 'other-month'} ${day.isSame(dayjs(), 'day') ? 'today' : ''} ${day.isSame(selectedDay, 'day') ? 'selected' : ''}`; + return ( +
handleDateClick(day)}> + {day.format('D')} + {filteredAppointments.length > 0 &&
{filteredAppointments.length}
} +
+ ); + })} +
+
+
+ ) : ( +
+
+
+
+

Fila de Espera

+
+
+
Filtros
+
setWaitlistSearch(e.target.value)} />Digite o nome do paciente, CPF ou nome do médico
+
+
+ Ordenar por: + +
+
+
+
{filaEsperaFiltrada.length} DE {filaEsperaData.length} SOLICITAÇÕES ENCONTRADAS
+
+
+
+ + + + + + + + + + + + {filaEsperaPaginada.length > 0 ? ( + filaEsperaPaginada.map((item, index) => ( + + + + + + + + )) + ) : ( + + + + )} + +
Nome do PacienteCPFMédico SolicitadoData da SolicitaçãoAções
{item?.Infos?.paciente_nome}{item?.Infos?.paciente_cpf}{item?.Infos?.medico_nome}{dayjs(item.agendamento.scheduled_at).format('DD/MM/YYYY')} + +
+
+ {showSpinner ? : (<>

Nenhuma solicitação encontrada.

)} +
+
+ {filaEsperaFiltrada.length > 0 && ( +
+
+ Itens por página: + +
+
+ Página {waitPage} de {waitTotalPages} • Mostrando {waitIndiceInicial + 1}-{Math.min(waitIndiceFinal, filaEsperaFiltrada.length)} de {filaEsperaFiltrada.length} + +
+
+ )} +
+
+
+
+
+
+ )} +
+
+ ) : ( + { + setPageConsulta(false); + fetchAppointments(); + }} + /> )} - + {showDeleteModal && }
- ) : ( - { - setPageConsulta(false); - fetchAppointments(); - }} - /> - )} - {showDeleteModal && } -
- ); -}; + ); +} export default Agendamento; diff --git a/src/PagesMedico/DoctorRelatorioManager.jsx b/src/PagesMedico/DoctorRelatorioManager.jsx index 13add57..6f86f00 100644 --- a/src/PagesMedico/DoctorRelatorioManager.jsx +++ b/src/PagesMedico/DoctorRelatorioManager.jsx @@ -46,7 +46,7 @@ const DoctorRelatorioManager = () => { if (authHeader) myHeaders.append('Authorization', authHeader); const requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; - // Tenta descobrir o ID do usuário logado para aplicar filtro por médico + let userId = null; let userFullName = null; try { @@ -60,12 +60,12 @@ const DoctorRelatorioManager = () => { console.warn('Não foi possível obter UserInfos (pode não estar logado):', err); } - // Monta a URL com possíveis filtros preferenciais + const baseUrl = "https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?select=*"; let data = []; if (userId) { - // 1) tenta por doctor_id + try { const res = await fetch(`${baseUrl}&doctor_id=eq.${userId}`, requestOptions); data = await res.json(); @@ -74,7 +74,7 @@ const DoctorRelatorioManager = () => { data = []; } - // 2) fallback para created_by (se vazio) + if ((!Array.isArray(data) || data.length === 0) && userId) { try { const res2 = await fetch(`${baseUrl}&created_by=eq.${userId}`, requestOptions); @@ -85,10 +85,9 @@ const DoctorRelatorioManager = () => { } } - // 3) fallback para requested_by com nome completo (se ainda vazio) if ((!Array.isArray(data) || data.length === 0) && userFullName) { try { - // encode para evitar problemas com espaços/caracteres especiais + const encodedName = encodeURIComponent(userFullName); const res3 = await fetch(`${baseUrl}&requested_by=eq.${encodedName}`, requestOptions); data = await res3.json(); @@ -99,7 +98,6 @@ const DoctorRelatorioManager = () => { } } - // Se não obteve userId ou nenhuma das tentativas acima retornou algo, busca tudo (comportamento anterior) if (!userId || (!Array.isArray(data) || data.length === 0)) { try { const resAll = await fetch(baseUrl, requestOptions); @@ -110,7 +108,7 @@ const DoctorRelatorioManager = () => { } } - // garante unicidade e ordenação por criação + const uniqueMap = new Map(); (Array.isArray(data) ? data : []).forEach(r => { if (r && r.id) uniqueMap.set(r.id, r); @@ -144,14 +142,14 @@ const DoctorRelatorioManager = () => { }; }, [authHeader]); - // Busca dados de pacientes e médicos baseados na lista final que aparece na tela + useEffect(() => { const fetchRelData = async () => { const pacientes = []; const medicos = []; for (let i = 0; i < relatoriosFinais.length; i++) { const rel = relatoriosFinais[i]; - // paciente + try { const pacienteRes = await GetPatientByID(rel.patient_id, authHeader); pacientes.push(Array.isArray(pacienteRes) ? pacienteRes[0] : pacienteRes); @@ -159,13 +157,12 @@ const DoctorRelatorioManager = () => { pacientes.push(null); } - // médico: prioriza campos com id (doctor_id ou created_by). Se tiver somente requested_by (nome), usa nome. try { if (rel.doctor_id) { const docRes = await GetDoctorByID(rel.doctor_id, authHeader); medicos.push(Array.isArray(docRes) ? docRes[0] : docRes); } else if (rel.created_by) { - // created_by costuma ser id + const docRes = await GetDoctorByID(rel.created_by, authHeader); medicos.push(Array.isArray(docRes) ? docRes[0] : docRes); } else if (rel.requested_by) { @@ -174,7 +171,6 @@ const DoctorRelatorioManager = () => { medicos.push({ full_name: '' }); } } catch (err) { - // fallback para requested_by se houver medicos.push({ full_name: rel.requested_by || '' }); } } @@ -190,7 +186,6 @@ const DoctorRelatorioManager = () => { }, [relatoriosFinais, authHeader]); const abrirModal = (relatorio, pageIndex) => { - // encontra índice global do relatório no array relatoriosFinais (para alinhar com pacientes/medicos) const globalIndex = relatoriosFinais.findIndex(r => r.id === relatorio.id); const indexToUse = globalIndex >= 0 ? globalIndex : (indiceInicial + pageIndex); setRelatorioModal(relatorio); @@ -198,7 +193,7 @@ const DoctorRelatorioManager = () => { setShowModal(true); }; - // Função para limpar filtros + const limparFiltros = () => { setTermoPesquisa(''); setFiltroExame(''); @@ -256,12 +251,11 @@ const DoctorRelatorioManager = () => { return (
{showModal && ( -
setShowModal(false)}> -
e.stopPropagation()}> +
+
-
+
Relatório de {pacientesComRelatorios[modalIndex]?.full_name}
-
@@ -290,11 +284,11 @@ const DoctorRelatorioManager = () => {
-
+
-
diff --git a/src/components/Header/Header.css b/src/components/Header/Header.css index 0a4737d..b07ccae 100644 --- a/src/components/Header/Header.css +++ b/src/components/Header/Header.css @@ -489,28 +489,27 @@ } } -/* permite que cliques "passem" através do header (exceto para os elementos interativos) */ .header-container { - pointer-events: none; /* header não captura cliques */ + pointer-events: none; } -/* mas permite que os controles no canto (telefone e profile) continuem clicáveis */ + .phone-icon-container, .profile-section { pointer-events: auto; } -/* Garantir pointer-events nos elementos do header e overlays criados por portal */ + .header-container { pointer-events: auto; } .phone-icon-container, .profile-section { pointer-events: auto; } -/* Força que os overlays criados por portal fiquem por cima */ + .logout-modal-overlay, .suporte-card-overlay, .chat-overlay { z-index: 110000 !important; pointer-events: auto !important; } -/* Pequeno ajuste visual dos botões do modal (pode se misturar com seu CSS atual) */ + .logout-cancel-button { padding: 10px 18px; border-radius: 8px; diff --git a/src/data/sidebar-items-adm.json b/src/data/sidebar-items-adm.json index 5b4c554..1eb3da2 100644 --- a/src/data/sidebar-items-adm.json +++ b/src/data/sidebar-items-adm.json @@ -25,5 +25,10 @@ "name": "Painel Administrativo", "icon": "file-bar-graph-fill", "url": "/admin/painel" + }, + { + "name": "Gestão de Usuários", + "icon": "people-fill", + "url": "/admin/gestao" } ] diff --git a/src/pages/DisponibilidadesDoctorPage.jsx b/src/pages/DisponibilidadesDoctorPage.jsx index ef488d8..5f79a67 100644 --- a/src/pages/DisponibilidadesDoctorPage.jsx +++ b/src/pages/DisponibilidadesDoctorPage.jsx @@ -38,6 +38,9 @@ const DisponibilidadesDoctorPage = () => { const [expandedDoctors, setExpandedDoctors] = useState({}); const [showSuggestions, setShowSuggestions] = useState(false); const [availabilityEdit, setAvailabilityEdit] = useState([]); + // Add the missing state variables + const [showDeleteModal, setShowDeleteModal] = useState(false); + const [selectedDisponibilidadeId, setSelectedDisponibilidadeId] = useState(null); const getHeaders = () => { const myHeaders = new Headers(); @@ -170,8 +173,24 @@ const DisponibilidadesDoctorPage = () => { if (!window.confirm("Deseja realmente excluir esta disponibilidade?")) return; try { const res = await fetch(`${ENDPOINT}?id=eq.${id}`, { method: "DELETE", headers: getHeaders() }); - if (res.ok) setDisponibilidades((prev) => prev.filter((d) => d.id !== id)); - } catch (error) {} + if (res.ok) { + setDisponibilidades((prev) => prev.filter((d) => d.id !== id)); + setShowDeleteModal(false); + setSelectedDisponibilidadeId(null); + } + } catch (error) { + console.error("Erro ao excluir disponibilidade:", error); + } + }; + + const handleOpenDeleteModal = (id) => { + setSelectedDisponibilidadeId(id); + setShowDeleteModal(true); + }; + + const handleCloseDeleteModal = () => { + setShowDeleteModal(false); + setSelectedDisponibilidadeId(null); }; const disponibilidadesAgrupadas = useMemo(() => { @@ -420,7 +439,16 @@ const DisponibilidadesDoctorPage = () => { {getStatusText(disp)} - {!disp.is_empty && } + + {!disp.is_empty && ( + + )} + ))} @@ -435,6 +463,51 @@ const DisponibilidadesDoctorPage = () => { )}
+ + {showDeleteModal && ( +
+
+
+
+
+ Confirmação de Exclusão +
+
+ +
+

+ Tem certeza que deseja excluir esta disponibilidade? +

+
+ +
+ + + +
+
+
+
+ )}
); }; diff --git a/src/pages/DoctorTable.jsx b/src/pages/DoctorTable.jsx index a0f3650..e5becd7 100644 --- a/src/pages/DoctorTable.jsx +++ b/src/pages/DoctorTable.jsx @@ -27,9 +27,8 @@ function TableDoctor({setDictInfo}) { const [showDeleteModal, setShowDeleteModal] = useState(false); const [selectedDoctorId, setSelectedDoctorId] = useState(null); - // Ordenação rápida - const [sortKey, setSortKey] = useState(null); // 'nome' | 'idade' | null - const [sortDir, setSortDir] = useState('asc'); // 'asc' | 'desc' + const [sortKey, setSortKey] = useState(null); + const [sortDir, setSortDir] = useState('asc'); const limparFiltros = () => { setSearch(""); @@ -147,7 +146,6 @@ function TableDoctor({setDictInfo}) { return resultado; }) : []; - const applySorting = (arr) => { if (!Array.isArray(arr) || !sortKey) return arr; const copy = [...arr]; @@ -277,7 +275,7 @@ function TableDoctor({setDictInfo}) {
- {/* Ordenação rápida */} +
Ordenar por: @@ -481,7 +479,6 @@ function TableDoctor({setDictInfo}) { - {/* Paginação */} {medicosFiltrados.length > 0 && (
@@ -554,15 +551,10 @@ function TableDoctor({setDictInfo}) { >
-
+
Confirmação de Exclusão
-
diff --git a/src/pages/EditPage.jsx b/src/pages/EditPage.jsx index 0f9bb18..dac83d8 100644 --- a/src/pages/EditPage.jsx +++ b/src/pages/EditPage.jsx @@ -9,6 +9,7 @@ import { useAuth } from '../components/utils/AuthProvider' const EditPage = ({DictInfo}) => { const navigate = useNavigate() const [PatientToPUT, setPatientPUT] = useState({}) + const [showSuccessModal, setShowSuccessModal] = useState(false) const { getAuthorizationHeader, isAuthenticated } = useAuth(); @@ -37,9 +38,15 @@ const HandlePutPatient = async () => { }; fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients?id=eq.${PatientToPUT.id}`,requestOptions) - .then(response => console.log(response)) + .then(response => { + console.log(response) + if (response.ok) { + setShowSuccessModal(true) + } + return response + }) .then(result => console.log(result)) - .catch(console.log("erro")) + .catch(error => console.log("erro", error)) }; @@ -52,6 +59,46 @@ const HandlePutPatient = async () => { formData={PatientToPUT} setFormData={setPatientPUT} /> + + {showSuccessModal && ( +
+
+
+
+
+ Paciente Editado +
+
+ +
+

+ Paciente editado com sucesso! +

+
+ +
+ +
+
+
+
+ )}
) diff --git a/src/pages/ExcecoesDisponibilidade.jsx b/src/pages/ExcecoesDisponibilidade.jsx index db2e034..e4f834b 100644 --- a/src/pages/ExcecoesDisponibilidade.jsx +++ b/src/pages/ExcecoesDisponibilidade.jsx @@ -1,4 +1,5 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; +import { useNavigate } from 'react-router-dom'; import dayjs from 'dayjs'; import 'dayjs/locale/pt-br'; import weekday from 'dayjs/plugin/weekday'; @@ -23,12 +24,10 @@ const getDateRange = (date, view) => { toDate = startDayjs.format('YYYY-MM-DD'); titleRange = startDayjs.format('DD/MM/YYYY'); } else if (view === 'semanal') { - // Padrão Dayjs: Sunday=0, Monday=1. - // startOf('week') pode ser Domingo ou Segunda, dependendo do locale. - // Se precisar forçar a Segunda-feira: + let weekStart = startDayjs.startOf('week'); - if (weekStart.day() !== 1) { // Se não for segunda-feira (1), ajusta - weekStart = startDayjs.weekday(1); // Vai para a segunda-feira desta semana + if (weekStart.day() !== 1) { + weekStart = startDayjs.weekday(1); } const weekEnd = weekStart.add(6, 'day'); @@ -52,12 +51,21 @@ const getDateRange = (date, view) => { const ExcecoesDisponibilidade = () => { const { getAuthorizationHeader } = useAuth(); + const navigate = useNavigate(); const [pageNovaExcecao, setPageNovaExcecao] = useState(false); const [excecoes, setExcecoes] = useState([]); const [loading, setLoading] = useState(false); + const [showDeleteModal, setShowDeleteModal] = useState(false); + const [selectedExceptionId, setSelectedExceptionId] = useState(null); + const [showSuccessModal, setShowSuccessModal] = useState(false); + const [successMessage, setSuccessMessage] = useState(''); const [filtroMedicoId, setFiltroMedicoId] = useState(''); const [filtroData, setFiltroData] = useState(dayjs().format('YYYY-MM-DD')); + const [listaDeMedicos, setListaDeMedicos] = useState([]); + const [searchTermDoctor, setSearchTermDoctor] = useState(''); + const [filteredDoctors, setFilteredDoctors] = useState([]); + const [selectedDoctor, setSelectedDoctor] = useState(null); const [visualizacao, setVisualizacao] = useState('diario'); @@ -123,8 +131,51 @@ const ExcecoesDisponibilidade = () => { fetchExcecoes(fromDate, toDate, filtroMedicoId); }, [fetchExcecoes, filtroMedicoId, fromDate, toDate]); + useEffect(() => { + const fetchDoctors = async () => { + const myHeaders = new Headers(); + const authHeader = resolveAuthHeader(); + if (authHeader) myHeaders.append("Authorization", authHeader); + if (API_KEY) myHeaders.append("apikey", API_KEY); + + try { + const response = await fetch('https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors?select=id,full_name', { + method: 'GET', + headers: myHeaders + }); + if (response.ok) { + const doctors = await response.json(); + setListaDeMedicos(doctors); + } + } catch (error) { + console.error('Erro ao buscar médicos:', error); + } + }; + fetchDoctors(); + }, []); + + const handleSearchDoctors = (term) => { + setSearchTermDoctor(term); + if (term.trim() === '') { + setFilteredDoctors([]); + return; + } + const filtered = listaDeMedicos.filter(doc => + doc.full_name.toLowerCase().includes(term.toLowerCase()) + ); + setFilteredDoctors(filtered); + }; + + const limparFiltros = () => { + setSearchTermDoctor(''); + setFilteredDoctors([]); + setSelectedDoctor(null); + setFiltroMedicoId(''); + setFiltroData(dayjs().format('YYYY-MM-DD')); + setVisualizacao('diario'); + }; + const deleteExcecao = async (id) => { - if (!window.confirm("Confirma exclusão desta exceção?")) return; const myHeaders = new Headers(); const authHeader = resolveAuthHeader(); if (authHeader) myHeaders.append("Authorization", authHeader); @@ -139,6 +190,9 @@ const ExcecoesDisponibilidade = () => { }); if (res.ok) { setExcecoes(prev => prev.filter(x => x.id !== id)); + setShowDeleteModal(false); + setSuccessMessage('Exceção excluída com sucesso!'); + setShowSuccessModal(true); } else { const text = await res.text(); console.error('Erro ao deletar exceção', res.status, text); @@ -163,7 +217,7 @@ const ExcecoesDisponibilidade = () => { return (
- {/* Título e Botão de Criação */} +

Gerenciar Exceções de Disponibilidade

-
+
+
+ + Filtros +
- {/* Filtros de Médico e Data */} -
-
- +
+
+ setFiltroMedicoId(e.target.value)} + className="form-control" + placeholder="Digite o nome do médico..." + value={searchTermDoctor} + onChange={(e) => handleSearchDoctors(e.target.value)} /> + Filtre as exceções por médico + {searchTermDoctor && filteredDoctors.length > 0 && ( +
+ {filteredDoctors.map((doc) => ( + + ))} +
+ )}
-
- - + + setFiltroData(e.target.value)} /> + Selecione a data base para visualização
- {/* Botões de Visualização (Dia/Semana/Mês) */} +
+
+ {selectedDoctor && ( + + + {selectedDoctor.full_name} + + )} +
+ {excecoes.length} DE {excecoes.length} EXCEÇÕES ENCONTRADAS +
+
+ + +
+
+ +
+ +
- {/* Tabela de Exceções (Título usa o titleRange calculado) */} +

Exceções em {titleRange} ({excecoes.length})

@@ -264,7 +368,10 @@ const ExcecoesDisponibilidade = () => { @@ -278,6 +385,89 @@ const ExcecoesDisponibilidade = () => {
+ + {showDeleteModal && ( +
+
+
+
+
+ Confirmação de Exclusão +
+
+ +
+

+ Tem certeza que deseja excluir esta exceção? +

+
+ +
+ + + +
+
+
+
+ )} + + + {showSuccessModal && ( +
+
+
+
+
+ Sucesso +
+
+ +
+

+ {successMessage} +

+
+ +
+ +
+
+
+
+ )}
); } diff --git a/src/pages/LaudoManager.jsx b/src/pages/LaudoManager.jsx index e603dfa..e881d77 100644 --- a/src/pages/LaudoManager.jsx +++ b/src/pages/LaudoManager.jsx @@ -32,7 +32,6 @@ const LaudoManager = () => { const [paginaAtual, setPaginaAtual] = useState(1); const [itensPorPagina, setItensPorPagina] = useState(10); - // agora guardamos a mensagem (null = sem aviso) const [noPermissionText, setNoPermissionText] = useState(null); const isSecretary = true; @@ -162,11 +161,11 @@ const LaudoManager = () => { const handleLiberarLaudo = async (relatorio) => { if (isSecretary) { - // MUDANÇA: mostrar "Ainda não implementado" + setNoPermissionText('Ainda não implementado'); return; } - // para médicos: implementação real já estava antes (mantive o bloco, caso queira) + try { const myHeaders = new Headers(); myHeaders.append('apikey', API_KEY); @@ -187,7 +186,6 @@ const LaudoManager = () => { throw new Error('Erro ao liberar laudo: ' + res.status + ' ' + txt); } - // refetch simples const refreshed = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/reports?select=*", { method: 'GET', headers: (() => { const h=new Headers(); h.append('apikey', API_KEY); if(authHeader) h.append('Authorization', authHeader); return h; })(), @@ -327,7 +325,7 @@ const LaudoManager = () => { Editar - {/* Removido o botão "Imprimir" daqui (agora no Ver Detalhes) */} +
- {/* Modal principal (detalhes) */} + {showModal && relatorioModal && ( -
setShowModal(false)}> -
e.stopPropagation()}> +
+
-
+
Relatório de {pacientesComRelatorios[modalIndex]?.full_name || relatorioModal.patient_name || 'Paciente'}
-
@@ -441,11 +438,11 @@ const LaudoManager = () => {
-
+
-
@@ -454,14 +451,13 @@ const LaudoManager = () => {
)} - {/* Modal Protocolo */} + {showProtocolModal && protocolForIndex && ( -
setShowProtocolModal(false)}> -
e.stopPropagation()}> +
+
-
+
Protocolo de Entrega - {protocolForIndex.relatorio?.patient_name || 'Paciente'}
-
@@ -474,14 +470,14 @@ const LaudoManager = () => {
-
+
-
@@ -490,17 +486,18 @@ const LaudoManager = () => {
)} - {/* Variável de aviso: mostra texto personalizado */} {noPermissionText && ( -
setNoPermissionText(null)}> -
e.stopPropagation()}> +
+
-
-
{noPermissionText}
-

{/* opcional descrição aqui */}

-
- -
+
+
Aviso
+
+
+

{noPermissionText}

+
+
+
diff --git a/src/pages/ProfilePage.jsx b/src/pages/ProfilePage.jsx index ab47356..a41bfe8 100644 --- a/src/pages/ProfilePage.jsx +++ b/src/pages/ProfilePage.jsx @@ -2,14 +2,6 @@ import React, { useState, useEffect, useCallback } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import "./style/ProfilePage.css"; - -const MOCK_API_BASE_URL = "https://mock.apidog.com/m1/1053378-0-default"; - - -const getLocalAvatar = () => localStorage.getItem('user_avatar'); -const setLocalAvatar = (avatarData) => localStorage.setItem('user_avatar', avatarData); -const clearLocalAvatar = () => localStorage.removeItem('user_avatar'); - const ROLES = { ADMIN: "Administrador", SECRETARY: "Secretária", @@ -36,7 +28,6 @@ const ProfilePage = () => { const [userEmail, setUserEmail] = useState("admin@squad23.com"); const [avatarUrl, setAvatarUrl] = useState(null); const [isEditingName, setIsEditingName] = useState(false); - const [isUploading, setIsUploading] = useState(false); const [error, setError] = useState(null); @@ -52,14 +43,21 @@ const ProfilePage = () => { useEffect(() => { const loadProfileData = () => { - - const localAvatar = getLocalAvatar(); + const localAvatar = localStorage.getItem('user_avatar'); if (localAvatar) { setAvatarUrl(localAvatar); } }; loadProfileData(); + + + const handleStorageChange = () => { + loadProfileData(); + }; + + window.addEventListener('storage', handleStorageChange); + return () => window.removeEventListener('storage', handleStorageChange); }, []); const handleNameSave = () => { @@ -83,104 +81,6 @@ const ProfilePage = () => { const handleClose = () => navigate(-1); - - const handleAvatarUpload = async (event) => { - const file = event.target.files[0]; - if (!file) return; - - setError(null); - - - const MAX_FILE_SIZE = 5 * 1024 * 1024; - const ACCEPTED_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; - - if (file.size > MAX_FILE_SIZE) { - setError("Arquivo muito grande. Máximo 5MB."); - return; - } - - if (!ACCEPTED_TYPES.includes(file.type)) { - setError("Tipo de arquivo não suportado. Use JPEG, PNG, GIF ou WebP."); - return; - } - - setIsUploading(true); - - try { - - try { - const result = await uploadAvatarToMockAPI(file); - - const newAvatarUrl = result.url || result.avatarUrl; - if (newAvatarUrl) { - setAvatarUrl(newAvatarUrl); - setLocalAvatar(newAvatarUrl); - console.log('Avatar enviado para API com sucesso'); - return; - } - } catch (apiError) { - - console.log('API não disponível, salvando localmente...'); - } - - - const reader = new FileReader(); - reader.onload = (e) => { - const imageDataUrl = e.target.result; - setLocalAvatar(imageDataUrl); - setAvatarUrl(imageDataUrl); - console.log('Avatar salvo localmente'); - }; - reader.readAsDataURL(file); - - } catch (error) { - - console.error('Erro no processamento:', error); - const reader = new FileReader(); - reader.onload = (e) => { - const imageDataUrl = e.target.result; - setLocalAvatar(imageDataUrl); - setAvatarUrl(imageDataUrl); - }; - reader.readAsDataURL(file); - } finally { - setIsUploading(false); - event.target.value = ''; - } - }; - - - const uploadAvatarToMockAPI = async (file) => { - const formData = new FormData(); - formData.append("avatar", file); - - const response = await fetch(`${MOCK_API_BASE_URL}/storage/v1/object/avatars/[path]`, { - method: "POST", - body: formData - }); - - if (!response.ok) { - - return null; - } - - return await response.json(); - }; - - - const clearAvatar = () => { - - fetch(`${MOCK_API_BASE_URL}/storage/v1/object/avatars/[path]`, { - method: "DELETE" - }).catch(() => { - - }); - - - clearLocalAvatar(); - setAvatarUrl(null); - }; - return (
@@ -203,7 +103,7 @@ const ProfilePage = () => { className="avatar-img" onError={() => { setAvatarUrl(null); - clearLocalAvatar(); + localStorage.removeItem('user_avatar'); }} /> ) : ( @@ -212,26 +112,15 @@ const ProfilePage = () => {
)}
- - - - {isUploading && ( -

- Processando imagem... -

- )} + +

+ Gerencie seu avatar no menu do perfil acima +

@@ -287,11 +176,6 @@ const ProfilePage = () => {
- {avatarUrl && ( - - )} - {/* Ordenação rápida (estilo compacto por select) */}
Ordenar por: @@ -550,11 +550,15 @@ function TablePaciente({ setCurrentPage, setPatientID,setDictInfo }) { - - - +