From 6e7c85e853526b2b7bc9c87f6113b2e85ab05b6a Mon Sep 17 00:00:00 2001 From: Lucas Santana Date: Fri, 20 Dec 2024 15:23:48 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20adiciona=20p=C3=A1gina=20de=20configura?= =?UTF-8?q?=C3=A7=C3=B5es=20do=20aluno?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Cria componente StudentSettingsPage - Adiciona rota de configurações - Implementa utils para classes condicionais - Atualiza navegação no dashboard do aluno --- package-lock.json | 301 +++++++++++++++++- package.json | 5 +- src/components/ui/avatar-upload.tsx | 40 +++ src/components/ui/date-picker.tsx | 27 ++ src/components/ui/input.tsx | 21 ++ src/components/ui/select.tsx | 39 +++ src/components/ui/tabs.tsx | 52 +++ src/lib/utils.ts | 6 + .../student-dashboard/StudentClassPage.tsx | 15 + .../student-dashboard/StudentDashboard.tsx | 12 + .../StudentDashboardLayout.tsx | 2 +- .../student-dashboard/StudentSettingsPage.tsx | 66 ++++ src/pages/student-dashboard/index.ts | 6 +- src/pages/student/SettingsPage.tsx | 71 +++++ src/routes/index.tsx | 21 ++ tsconfig.json | 5 +- 16 files changed, 678 insertions(+), 11 deletions(-) create mode 100644 src/components/ui/avatar-upload.tsx create mode 100644 src/components/ui/date-picker.tsx create mode 100644 src/components/ui/input.tsx create mode 100644 src/components/ui/select.tsx create mode 100644 src/components/ui/tabs.tsx create mode 100644 src/lib/utils.ts create mode 100644 src/pages/student-dashboard/StudentClassPage.tsx create mode 100644 src/pages/student-dashboard/StudentDashboard.tsx create mode 100644 src/pages/student-dashboard/StudentSettingsPage.tsx create mode 100644 src/pages/student/SettingsPage.tsx diff --git a/package-lock.json b/package-lock.json index bfce122..618e034 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,15 @@ "name": "vite-react-typescript-starter", "version": "0.0.0", "dependencies": { + "@radix-ui/react-tabs": "^1.1.2", "@supabase/supabase-js": "^2.39.7", + "clsx": "^2.1.1", "lucide-react": "^0.344.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.28.0", - "resend": "^3.2.0" + "resend": "^3.2.0", + "tailwind-merge": "^2.5.5" }, "devDependencies": { "@eslint/js": "^9.9.1", @@ -1002,6 +1005,275 @@ "node": ">=14" } }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz", + "integrity": "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", + "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz", + "integrity": "sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collection": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", + "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.2.tgz", + "integrity": "sha512-9u/tQJMcC2aGq7KXpGivMm1mgq7oRJKXphDwdypPd/j21j/2znamPU8WkXgnhUaTrSFNIt8XhOyCAupg8/GbwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-roving-focus": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@react-email/render": { "version": "0.0.16", "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.16.tgz", @@ -1396,13 +1668,13 @@ "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", - "dev": true + "devOptional": true }, "node_modules/@types/react": { "version": "18.3.17", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.17.tgz", "integrity": "sha512-opAQ5no6LqJNo9TqnxBKsgnkIYHozW9KSTlFVoSUJYh1Fl/sswkEoqIugRSm7tbh6pABtYjGAjW+GOS23j8qbw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -1413,7 +1685,7 @@ "version": "18.3.5", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", - "dev": true, + "devOptional": true, "license": "MIT", "peerDependencies": { "@types/react": "^18.0.0" @@ -1974,6 +2246,15 @@ "node": ">= 6" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -2049,7 +2330,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "devOptional": true }, "node_modules/debug": { "version": "4.3.7", @@ -4086,6 +4367,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwind-merge": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", + "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", diff --git a/package.json b/package.json index b50cf47..6c226a1 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,15 @@ "format": "prettier --write \"src/**/*.{ts,tsx}\"" }, "dependencies": { + "@radix-ui/react-tabs": "^1.1.2", "@supabase/supabase-js": "^2.39.7", + "clsx": "^2.1.1", "lucide-react": "^0.344.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.28.0", - "resend": "^3.2.0" + "resend": "^3.2.0", + "tailwind-merge": "^2.5.5" }, "devDependencies": { "@eslint/js": "^9.9.1", diff --git a/src/components/ui/avatar-upload.tsx b/src/components/ui/avatar-upload.tsx new file mode 100644 index 0000000..d6de155 --- /dev/null +++ b/src/components/ui/avatar-upload.tsx @@ -0,0 +1,40 @@ +import React, { useRef, useState } from 'react'; +import { Camera } from 'lucide-react'; + +export function AvatarUpload(): JSX.Element { + const [preview, setPreview] = useState(); + const fileInputRef = useRef(null); + + const handleFileChange = (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + setPreview(reader.result as string); + }; + reader.readAsDataURL(file); + } + }; + + return ( +
+
fileInputRef.current?.click()} + > + {preview ? ( + Avatar + ) : ( + + )} +
+ +
+ ); +} \ No newline at end of file diff --git a/src/components/ui/date-picker.tsx b/src/components/ui/date-picker.tsx new file mode 100644 index 0000000..dab76c4 --- /dev/null +++ b/src/components/ui/date-picker.tsx @@ -0,0 +1,27 @@ +import React from 'react'; + +interface DatePickerProps { + label?: string; + name: string; + value?: string; + onChange?: (date: string) => void; +} + +export function DatePicker({ label, name, value, onChange }: DatePickerProps): JSX.Element { + return ( +
+ {label && ( + + )} + onChange?.(e.target.value)} + className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-purple-500" + /> +
+ ); +} \ No newline at end of file diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..951a23e --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,21 @@ +import React from 'react'; + +interface InputProps extends React.InputHTMLAttributes { + label?: string; +} + +export function Input({ label, className, ...props }: InputProps): JSX.Element { + return ( +
+ {label && ( + + )} + +
+ ); +} \ No newline at end of file diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx new file mode 100644 index 0000000..da15ef8 --- /dev/null +++ b/src/components/ui/select.tsx @@ -0,0 +1,39 @@ +import React from 'react'; + +interface SelectOption { + value: string; + label: string; +} + +interface SelectProps { + label?: string; + name: string; + options: SelectOption[]; + value?: string; + onChange?: (value: string) => void; +} + +export function Select({ label, name, options, value, onChange }: SelectProps): JSX.Element { + return ( +
+ {label && ( + + )} + +
+ ); +} \ No newline at end of file diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx new file mode 100644 index 0000000..402b5a4 --- /dev/null +++ b/src/components/ui/tabs.tsx @@ -0,0 +1,52 @@ +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" +import { cn } from "../../lib/utils" + +const Tabs = TabsPrimitive.Root + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsList.displayName = TabsPrimitive.List.displayName + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsContent.displayName = TabsPrimitive.Content.displayName + +export { Tabs, TabsList, TabsTrigger, TabsContent } \ No newline at end of file diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..f7654e8 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} \ No newline at end of file diff --git a/src/pages/student-dashboard/StudentClassPage.tsx b/src/pages/student-dashboard/StudentClassPage.tsx new file mode 100644 index 0000000..e5a1cf2 --- /dev/null +++ b/src/pages/student-dashboard/StudentClassPage.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { useParams } from 'react-router-dom'; + +export function StudentClassPage(): JSX.Element { + const { classId } = useParams(); + + return ( +
+

+ Turma {classId} +

+ {/* Conteúdo da página da turma será implementado aqui */} +
+ ); +} \ No newline at end of file diff --git a/src/pages/student-dashboard/StudentDashboard.tsx b/src/pages/student-dashboard/StudentDashboard.tsx new file mode 100644 index 0000000..6b75d01 --- /dev/null +++ b/src/pages/student-dashboard/StudentDashboard.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +export function StudentDashboard(): JSX.Element { + return ( +
+

+ Bem-vindo ao Dashboard +

+ {/* Conteúdo do dashboard será implementado aqui */} +
+ ); +} \ No newline at end of file diff --git a/src/pages/student-dashboard/StudentDashboardLayout.tsx b/src/pages/student-dashboard/StudentDashboardLayout.tsx index 14a9ae3..d7edae3 100644 --- a/src/pages/student-dashboard/StudentDashboardLayout.tsx +++ b/src/pages/student-dashboard/StudentDashboardLayout.tsx @@ -92,7 +92,7 @@ export function StudentDashboardLayout() { className={({ isActive }) => `flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${ isActive - ? 'bg-purple-50 text-purple-700' + ? 'bg-purple-50 text-purple-600' : 'text-gray-600 hover:bg-gray-50' }` } diff --git a/src/pages/student-dashboard/StudentSettingsPage.tsx b/src/pages/student-dashboard/StudentSettingsPage.tsx new file mode 100644 index 0000000..d7224c9 --- /dev/null +++ b/src/pages/student-dashboard/StudentSettingsPage.tsx @@ -0,0 +1,66 @@ +import { Tabs, TabsList, TabsTrigger, TabsContent } from '../../components/ui/tabs'; +import { Input } from '../../components/ui/input'; +import { DatePicker } from '../../components/ui/date-picker'; +import { Select } from '../../components/ui/select'; +import { AvatarUpload } from '../../components/ui/avatar-upload'; + +export function StudentSettingsPage() { + return ( +
+

+ Configurações do Perfil +

+ + + + Informações Pessoais + Preferências + Acessibilidade + Notificações + + + +
+
+ +
+

Foto do Perfil

+

+ JPG ou PNG, máximo 2MB +

+
+
+ +
+ + + + + + +