diff --git a/back/src/auth/auth.service.ts b/back/src/auth/auth.service.ts index 43567e8..16ee860 100644 --- a/back/src/auth/auth.service.ts +++ b/back/src/auth/auth.service.ts @@ -25,6 +25,7 @@ export class AuthService { sub: user.id, username: user.username, roles: user.roles, + picture: user.picture, }; return { access_token: await this.jwtService.signAsync(payload) }; diff --git a/back/src/users/entities/user.entity.ts b/back/src/users/entities/user.entity.ts index 2dd3592..41ab670 100644 --- a/back/src/users/entities/user.entity.ts +++ b/back/src/users/entities/user.entity.ts @@ -16,4 +16,7 @@ export class User { @Column() roles: string; + + @Column() + picture: string; } diff --git a/back/src/users/roles/role.enum.ts b/back/src/users/roles/role.enum.ts index f62dd38..91c2ed3 100644 --- a/back/src/users/roles/role.enum.ts +++ b/back/src/users/roles/role.enum.ts @@ -1,5 +1,6 @@ export enum Role { Public = 'public', User = 'user', + Manager = 'manager', Admin = 'admin', } diff --git a/back/src/users/users.service.ts b/back/src/users/users.service.ts index a3c4ca8..8340765 100644 --- a/back/src/users/users.service.ts +++ b/back/src/users/users.service.ts @@ -9,6 +9,7 @@ export type UserType = { username: string; password: string; roles: Role[]; + picture: string; }; @Injectable() @@ -29,6 +30,7 @@ export class UsersService { username: db_user.username, password: db_user.password, roles: db_user.roles.split(';') as Role[], + picture: db_user.picture, }; console.log(user); return user; diff --git a/docker-compose.yml b/docker-compose.yml index a40474e..d686910 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: "1.1" +version: "1.2" services: mysql: diff --git a/front/.env b/front/.env index d7e5fe9..75ef813 100644 --- a/front/.env +++ b/front/.env @@ -1,3 +1,6 @@ -NEXTAUTH_URL=http://localhost:3016 +NEXT_PUBLIC_URL=http://localhost:3016 +NEXT_PUBLIC_API_URL=http://localhost:3016 + # GEN AUTH_SECRET: $ openssl rand -base64 32 NEXTAUTH_SECRET=6lHRWUvCBtqlgTWc6aFn6s6PudYjuN6oUY+RrcEntTU= +NEXTAUTH_URL=http://localhost:3016 diff --git a/front/src/app/(home)/page.tsx b/front/src/app/(home)/page.tsx index 7f16d18..0f918c7 100644 --- a/front/src/app/(home)/page.tsx +++ b/front/src/app/(home)/page.tsx @@ -1,5 +1,3 @@ -import ThemeSwitcher from "@/modules/common/theme-switcher"; - export default function Home() { return (
Main page -
); } diff --git a/front/src/modules/auth/components/log-in/log-in.module.scss b/front/src/modules/auth/components/log-in/log-in.module.scss index 27fd6af..95be06c 100644 --- a/front/src/modules/auth/components/log-in/log-in.module.scss +++ b/front/src/modules/auth/components/log-in/log-in.module.scss @@ -12,8 +12,8 @@ border-radius: 0.4rem; background-image: linear-gradient( 16deg, - rgba($color-primary-light-rgb, 0.3), - rgba($color-primary-light-rgb, 0.2) + rgba($color-primary-90-rgb, 0.3), + rgba($color-primary-90-rgb, 0.2) ); .heading { @@ -21,7 +21,7 @@ text-align: center; background-color: #e5e5f7; opacity: 0.8; - text-shadow: rgba($color-grey-dark, 0.3); + text-shadow: rgba($color-grey-10, 0.3); padding: 2rem 4rem 2rem; @@ -35,8 +35,8 @@ calc(0.5 * var(--s)) calc(0.5 * var(--s) * 0.577), repeating-conic-gradient( from 30deg, - $color-grey-medium 0 60deg, - $color-grey-light 0 120deg, + $color-grey-30 0 60deg, + $color-grey-90 0 120deg, $color-white 0 180deg ); background-size: var(--s) calc(var(--s) * 0.577); @@ -61,7 +61,7 @@ font-size: inherit; margin-left: 0.8em; - color: $color-grey-dark; + color: $color-grey-10; transition: all 0.3s; } @@ -71,7 +71,7 @@ color: $color-foreground; - background: rgba($color-primary-light-rgb, 0.5); + background: rgba($color-primary-90-rgb, 0.5); border: none; border-bottom: 2px solid transparent; border-radius: 2px; @@ -79,7 +79,7 @@ transition: all 0.2s; &::placeholder { - color: $color-grey-dark; + color: $color-grey-10; } &:focus { diff --git a/front/src/modules/auth/components/sign-in-button/index.ts b/front/src/modules/auth/components/sign-in-button/index.ts new file mode 100644 index 0000000..005ef10 --- /dev/null +++ b/front/src/modules/auth/components/sign-in-button/index.ts @@ -0,0 +1,3 @@ +"use client"; + +export { SignInButton as default } from "./sign-in-button.component"; diff --git a/front/src/modules/auth/components/sign-in-button/sign-in-button.component.tsx b/front/src/modules/auth/components/sign-in-button/sign-in-button.component.tsx new file mode 100644 index 0000000..ffc1f3b --- /dev/null +++ b/front/src/modules/auth/components/sign-in-button/sign-in-button.component.tsx @@ -0,0 +1,10 @@ +import { signIn } from "next-auth/react"; +import styles from "./sign-in-button.module.scss"; + +export const SignInButton = () => { + return ( + + ); +}; diff --git a/front/src/modules/auth/components/sign-in-button/sign-in-button.module.scss b/front/src/modules/auth/components/sign-in-button/sign-in-button.module.scss new file mode 100644 index 0000000..f54e640 --- /dev/null +++ b/front/src/modules/auth/components/sign-in-button/sign-in-button.module.scss @@ -0,0 +1,2 @@ +.button { +} diff --git a/front/src/modules/auth/components/sign-out-button/index.ts b/front/src/modules/auth/components/sign-out-button/index.ts new file mode 100644 index 0000000..504616a --- /dev/null +++ b/front/src/modules/auth/components/sign-out-button/index.ts @@ -0,0 +1,3 @@ +"use client"; + +export { SignOutButton as default } from "./sign-out-button.component"; diff --git a/front/src/modules/auth/components/sign-out-button/sign-out-button.component.tsx b/front/src/modules/auth/components/sign-out-button/sign-out-button.component.tsx new file mode 100644 index 0000000..103cc0a --- /dev/null +++ b/front/src/modules/auth/components/sign-out-button/sign-out-button.component.tsx @@ -0,0 +1,10 @@ +import { signOut } from "next-auth/react"; +import styles from "./sign-out-button.module.scss"; + +export const SignOutButton = () => { + return ( + + ); +}; diff --git a/front/src/modules/auth/components/sign-out-button/sign-out-button.module.scss b/front/src/modules/auth/components/sign-out-button/sign-out-button.module.scss new file mode 100644 index 0000000..f54e640 --- /dev/null +++ b/front/src/modules/auth/components/sign-out-button/sign-out-button.module.scss @@ -0,0 +1,2 @@ +.button { +} diff --git a/front/src/modules/auth/components/user-dropdown/index.ts b/front/src/modules/auth/components/user-dropdown/index.ts index b255352..1114380 100644 --- a/front/src/modules/auth/components/user-dropdown/index.ts +++ b/front/src/modules/auth/components/user-dropdown/index.ts @@ -1 +1 @@ -export { UserDropdown } from "./user-dropdown.component"; +export { UserDropdown as default } from "./user-dropdown.component"; diff --git a/front/src/modules/auth/components/user-dropdown/user-dropdown.component.tsx b/front/src/modules/auth/components/user-dropdown/user-dropdown.component.tsx index 98e5334..802ffab 100644 --- a/front/src/modules/auth/components/user-dropdown/user-dropdown.component.tsx +++ b/front/src/modules/auth/components/user-dropdown/user-dropdown.component.tsx @@ -1,14 +1,16 @@ -import { UserFrame } from "../user-frame"; import styles from "./user-dropdown.module.scss"; +import UserPanel from "../user-panel"; +import { UserFrame } from "../user-frame"; -export const UserDropdown = () => { +export const UserDropdown = async () => { return (
-
- +
+ +
); }; diff --git a/front/src/modules/auth/components/user-dropdown/user-dropdown.module.scss b/front/src/modules/auth/components/user-dropdown/user-dropdown.module.scss index 20b6c83..772baae 100644 --- a/front/src/modules/auth/components/user-dropdown/user-dropdown.module.scss +++ b/front/src/modules/auth/components/user-dropdown/user-dropdown.module.scss @@ -1,8 +1,27 @@ .container { + position: relative; + overflow: visible; + .avatar__container { width: 6rem; height: 6rem; - font-size: 3rem; + font-size: 3.4rem; + padding: 0.5rem; + } + + .dropdown__container { + position: absolute; + right: 0; + + opacity: 0; + visibility: hidden; + + transition: all 0.2s; + } + + &:hover > .dropdown__container { + opacity: 1; + visibility: visible; } } diff --git a/front/src/modules/auth/components/user-frame/user-frame.component.tsx b/front/src/modules/auth/components/user-frame/user-frame.component.tsx index 963a107..b2e9ad8 100644 --- a/front/src/modules/auth/components/user-frame/user-frame.component.tsx +++ b/front/src/modules/auth/components/user-frame/user-frame.component.tsx @@ -1,16 +1,20 @@ -import { getServerSession } from "next-auth/next"; -import { authOptions } from "../../configs/auth.options"; import Image from "next/image"; import styles from "./user-frame.module.scss"; +import { getServerSession } from "next-auth"; +import SignInButton from "../sign-in-button"; export async function UserFrame() { - const session = await getServerSession(authOptions); + const session = await getServerSession(); + + if (!session) { + return ; + } return (
- {getInitialsFromName(session?.user?.name || "")} + {getInitialsFromName(session?.user?.name || "00")} span { @@ -18,6 +18,6 @@ font-size: inherit; text-transform: uppercase; - color: $color-grey-medium; + color: $color-grey-30; } } diff --git a/front/src/modules/auth/components/user-panel/index.ts b/front/src/modules/auth/components/user-panel/index.ts new file mode 100644 index 0000000..2af2a2e --- /dev/null +++ b/front/src/modules/auth/components/user-panel/index.ts @@ -0,0 +1,3 @@ +"use client"; + +export { UserPanel as default } from "./user-panel.component"; diff --git a/front/src/modules/auth/components/user-panel/user-panel.component.tsx b/front/src/modules/auth/components/user-panel/user-panel.component.tsx new file mode 100644 index 0000000..7f8d06f --- /dev/null +++ b/front/src/modules/auth/components/user-panel/user-panel.component.tsx @@ -0,0 +1,21 @@ +import styles from "./user-panel.module.scss"; +import SignOutButton from "../sign-out-button"; +import { useSession } from "next-auth/react"; +import ThemeSwitcher from "@/modules/common/components/theme-switcher"; + +export function UserPanel() { + const session = useSession(); + + return ( + + ); +} diff --git a/front/src/modules/auth/components/user-panel/user-panel.module.scss b/front/src/modules/auth/components/user-panel/user-panel.module.scss new file mode 100644 index 0000000..045ef8b --- /dev/null +++ b/front/src/modules/auth/components/user-panel/user-panel.module.scss @@ -0,0 +1,36 @@ +.frame { + list-style: none; + min-width: 15rem; + display: flex; + flex-direction: column; + gap: 1.8rem 0.6rem; + + padding: 1.2rem 1.8rem; + + border-radius: 6px; + background-color: $color-foreground; + color: $color-background; + + & .user { + font-size: 1.6rem; + + &__name { + } + + &__roles { + list-style: none; + + display: flex; + flex-wrap: wrap; + gap: 0.4rem; + + & .role__chip { + padding: 0.4rem 0.6rem; + + border-radius: 4px; + background-color: $color-grey-90; + color: $color-grey-10; + } + } + } +} diff --git a/front/src/modules/auth/configs/auth.options.ts b/front/src/modules/auth/configs/auth.options.ts index d62439f..4a1fbf4 100644 --- a/front/src/modules/auth/configs/auth.options.ts +++ b/front/src/modules/auth/configs/auth.options.ts @@ -7,6 +7,7 @@ export const authOptions: AuthOptions = { }, pages: { signIn: "/auth/log-in", + signOut: "/", }, providers: [ CredentialsProvider({ @@ -39,6 +40,7 @@ export const authOptions: AuthOptions = { sub: string; username: string; roles: Role[]; + picture: string; iat: number; exp: number; }; @@ -50,7 +52,7 @@ export const authOptions: AuthOptions = { const user: User = { id: token_payload.username, roles: token_payload.roles, - image: "https://picsum.photos/200/300", + image: token_payload.picture, name: token_payload.username, apiSession: { accessToken: response_body.access_token, diff --git a/front/src/modules/auth/types/next-auth.d.ts b/front/src/modules/auth/types/next-auth.d.ts index 04df79e..7e8d5fb 100644 --- a/front/src/modules/auth/types/next-auth.d.ts +++ b/front/src/modules/auth/types/next-auth.d.ts @@ -2,7 +2,7 @@ import NextAuth, { DefaultSession } from "next-auth"; import { JWT, DefaultJWT } from "next-auth/jwt"; declare module "next-auth" { - type Role = "user" | "admin"; + type Role = "user" | "manager" | "admin"; interface ApiSession { accessToken: string; refreshToken?: string; @@ -16,6 +16,7 @@ declare module "next-auth" { } interface Session extends DefaultSession { + user?: Omit; apiSession?: ApiSession; } } diff --git a/front/src/modules/common/components/header/header.component.tsx b/front/src/modules/common/components/header/header.component.tsx deleted file mode 100644 index e6bf004..0000000 --- a/front/src/modules/common/components/header/header.component.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { UserDropdown } from "@/modules/auth/components/user-dropdown"; - -export const Header = () => { - return ; -}; diff --git a/front/src/modules/common/components/header/header.module.scss b/front/src/modules/common/components/header/header.module.scss deleted file mode 100644 index e69de29..0000000 diff --git a/front/src/modules/common/components/header/index.ts b/front/src/modules/common/components/header/index.ts deleted file mode 100644 index 67c8585..0000000 --- a/front/src/modules/common/components/header/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { Header } from "./header.component"; diff --git a/front/src/modules/common/components/navbar-header/index.ts b/front/src/modules/common/components/navbar-header/index.ts new file mode 100644 index 0000000..49c0471 --- /dev/null +++ b/front/src/modules/common/components/navbar-header/index.ts @@ -0,0 +1,3 @@ +"use client"; + +export { NavbarHeader as default } from "./navbar-header.component"; diff --git a/front/src/modules/common/components/navbar-header/navbar-header.component.tsx b/front/src/modules/common/components/navbar-header/navbar-header.component.tsx new file mode 100644 index 0000000..af0e8b4 --- /dev/null +++ b/front/src/modules/common/components/navbar-header/navbar-header.component.tsx @@ -0,0 +1,18 @@ +import Link from "next/link"; +import styles from "./navbar-header.module.scss"; + +import { PropsWithChildren } from "react"; + +/* + * Receives the user component as a children in order to fetch it from the server and allow quick session information fetch + * */ +export const NavbarHeader = (props: PropsWithChildren) => { + return ( +
+ + LoGo + + +
+ ); +}; diff --git a/front/src/modules/common/components/navbar-header/navbar-header.module.scss b/front/src/modules/common/components/navbar-header/navbar-header.module.scss new file mode 100644 index 0000000..b39432a --- /dev/null +++ b/front/src/modules/common/components/navbar-header/navbar-header.module.scss @@ -0,0 +1,25 @@ +.header { + position: sticky; + top: 1.2rem; + left: 0; + + display: flex; + justify-content: space-between; + + margin: 1.2rem; + box-sizing: border-box; + border-radius: 8px; + + padding: 0.4rem 1.8rem; + background-color: $color-white; + box-shadow: 0 1px 3px rgba($color-grey-10-rgb, 0.3); + color: $color-background; + + .logo { + display: flex; + align-items: center; + + font-size: 2.6rem; + font-weight: bold; + } +} diff --git a/front/src/modules/common/theme-switcher/index.ts b/front/src/modules/common/components/theme-switcher/index.ts similarity index 100% rename from front/src/modules/common/theme-switcher/index.ts rename to front/src/modules/common/components/theme-switcher/index.ts diff --git a/front/src/modules/common/theme-switcher/theme-switcher.component.tsx b/front/src/modules/common/components/theme-switcher/theme-switcher.component.tsx similarity index 100% rename from front/src/modules/common/theme-switcher/theme-switcher.component.tsx rename to front/src/modules/common/components/theme-switcher/theme-switcher.component.tsx diff --git a/front/src/modules/common/theme-switcher/theme-switcher.module.scss b/front/src/modules/common/components/theme-switcher/theme-switcher.module.scss similarity index 100% rename from front/src/modules/common/theme-switcher/theme-switcher.module.scss rename to front/src/modules/common/components/theme-switcher/theme-switcher.module.scss diff --git a/front/src/modules/common/layouts/home/home.layout.tsx b/front/src/modules/common/layouts/home/home.layout.tsx index d6fa389..0df89b7 100644 --- a/front/src/modules/common/layouts/home/home.layout.tsx +++ b/front/src/modules/common/layouts/home/home.layout.tsx @@ -1,12 +1,15 @@ import { PropsWithChildren } from "react"; import styles from "./home.module.scss"; -import { Header } from "../../components/header"; +import NavbarHeader from "../../components/navbar-header"; +import UserDropdown from "@/modules/auth/components/user-dropdown"; export const HomeLayout: React.FC = ({ children }) => { return (
-
+ + + {children}
); diff --git a/front/src/modules/common/layouts/home/home.module.scss b/front/src/modules/common/layouts/home/home.module.scss index 8b13789..0aa9b1b 100644 --- a/front/src/modules/common/layouts/home/home.module.scss +++ b/front/src/modules/common/layouts/home/home.module.scss @@ -1 +1,3 @@ - +.container { + background-color: $color-background; +} diff --git a/front/src/styles/_variables.scss b/front/src/styles/_variables.scss index 95bd6b3..5197fa4 100644 --- a/front/src/styles/_variables.scss +++ b/front/src/styles/_variables.scss @@ -8,11 +8,13 @@ $color-primary-light-rgb: var(--color-primary-light-rgb); $color-primary-dark-rgb: var(--color-primary-dark-rgb); $color-secondary: #ff7730; -$color-background: var(--color-white); +$color-background: var(--color-grey-90); $color-foreground: var(--color-black); $color-white: var(--color-white); -$color-grey-light: var(--color-grey-light); -$color-grey-medium: var(--color-grey-medium); -$color-grey-dark: var(--color-grey-dark); +$color-grey-90: var(--color-grey-90); +$color-grey-60: var(--color-grey-60); +$color-grey-30: var(--color-grey-30); +$color-grey-10: var(--color-grey-10); +$color-grey-10-rgb: var(--color-grey-10-rgb); diff --git a/front/src/styles/main.scss b/front/src/styles/main.scss index b53bf52..1eecbbb 100644 --- a/front/src/styles/main.scss +++ b/front/src/styles/main.scss @@ -5,9 +5,12 @@ --color-white: #fafafa; --color-black: #101010; - --color-grey-dark: #495057; - --color-grey-medium: #adb5bd; - --color-grey-light: #dee2e6; + --color-grey-10: #171717; + --color-grey-30: #242424; + --color-grey-60: #363636; + --color-grey-90: #bbbbbb; + --color-grey-90-rgb: 153, 153, 153; + --color-grey-10-rgb: 23, 23, 23; --color-primary: #9c89b8; --color-primary-light: #b8bedd; @@ -24,13 +27,14 @@ --color-grey-dark: #dee2e6; --color-grey-medium: #adb5bd; --color-grey-light: #495057; + --color-grey-dark-rgb: 222, 226, 230; - --color-primary: #56577d; - --color-primary-light: #b8bedd; - --color-primary-dark: #9c89b8; - --color-primary-rgb: 86, 87, 125; - --color-primary-light-rgb: 184, 190, 221; - --color-primary-dark-rgb: 156, 137, 184; + --color-grey-10: #bbbbbb; + --color-grey-30: #363636; + --color-grey-60: #242424; + --color-grey-90: #171717; + --color-grey-90-rgb: 23, 23, 23; + --color-grey-10-rgb: 153, 153, 153; } *, diff --git a/mysql/dump/dump.sql b/mysql/dump/dump.sql index b9e486f..083d425 100755 --- a/mysql/dump/dump.sql +++ b/mysql/dump/dump.sql @@ -4,6 +4,7 @@ CREATE TABLE user ( username VARCHAR(50) NOT NULL, password VARCHAR(255) NOT NULL, roles VARCHAR(255) NOT NULL, + picture VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); @@ -15,9 +16,9 @@ CREATE TABLE example ( created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -INSERT INTO user (username, password, roles) VALUES -('dqnid', '$2b$10$DDGh9u4yiTY9FJx2faFPlucBbTB6Y3i8YkH7AEztcpeaKv08AjdrW', 'admin'), -('albi', '$2b$10$DDGh9u4yiTY9FJx2faFPlucBbTB6Y3i8YkH7AEztcpeaKv08AjdrW', 'admin'); +INSERT INTO user (username, password, roles, picture) VALUES +('dqnid', '$2b$10$DDGh9u4yiTY9FJx2faFPlucBbTB6Y3i8YkH7AEztcpeaKv08AjdrW', 'user;manager;admin', 'https://picsum.photos/200/300'), +('albi', '$2b$10$DDGh9u4yiTY9FJx2faFPlucBbTB6Y3i8YkH7AEztcpeaKv08AjdrW', 'admin', NULL); INSERT INTO example (name, description, image) VALUES ('dqnid', 'This is a short text stored in a mysql database', 'https://picsum.photos/200/300'),