refactor
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import NavLinks from '@/app/ui/nav-links'
|
import NavLinks from '@/app/ui/nav-links'
|
||||||
import styles from '@/app/styles/page.module.scss'
|
|
||||||
import HeaderPanel from '@/app/ui/header/headerPanel';
|
import HeaderPanel from '@/app/ui/header/headerPanel';
|
||||||
import { getQueryClient } from '@/app/providers/getQueryClient';
|
import { getQueryClient } from '@/app/providers/getQueryClient';
|
||||||
import { HydrationBoundary, dehydrate } from '@tanstack/react-query';
|
import { HydrationBoundary, dehydrate } from '@tanstack/react-query';
|
||||||
@@ -14,9 +13,9 @@ export default async function Layout({ children }: { children: React.ReactNode }
|
|||||||
<div className="flex">
|
<div className="flex">
|
||||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||||
<NavLinks />
|
<NavLinks />
|
||||||
<div className={`${styles['main-containter-wrapper']}`}>
|
<div className="main-containter-wrapper">
|
||||||
<HeaderPanel />
|
<HeaderPanel />
|
||||||
<main className={`${styles['main-containter']}`}>
|
<main className="main-containter">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,31 +1,6 @@
|
|||||||
'use server'
|
'use server'
|
||||||
import { getSessionData } from '@/app/actions/session';
|
import { getSessionData } from '@/app/actions/session';
|
||||||
import { localDevelopmentUrl, testUserData, API_BASE_URL } from '@/app/actions/definitions';
|
import { testUserData, API_BASE_URL } from '@/app/actions/definitions';
|
||||||
|
|
||||||
const FRUITS_URL = 'https://www.fruityvice.com/api/fruit/';
|
|
||||||
const ALL = 'all';
|
|
||||||
|
|
||||||
export async function fetchFruits() {
|
|
||||||
try {
|
|
||||||
const response = await fetch(FRUITS_URL + ALL, { 'method': 'GET' });
|
|
||||||
let parsed = await response.json();
|
|
||||||
return parsed;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error:', error);
|
|
||||||
throw new Error('Failed to fetch fruits data.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchFruit(id: number) {
|
|
||||||
try {
|
|
||||||
const response = await fetch(FRUITS_URL + id, { 'method': 'GET' });
|
|
||||||
let parsed = await response.json();
|
|
||||||
return parsed;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error:', error);
|
|
||||||
throw new Error('Failed to fetch fruits data.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getUserData() {
|
export async function getUserData() {
|
||||||
const userEmail = await getSessionData('email');
|
const userEmail = await getSessionData('email');
|
||||||
|
|||||||
@@ -6,6 +6,19 @@
|
|||||||
@use './privacy-and-terms-pages.scss';
|
@use './privacy-and-terms-pages.scss';
|
||||||
@use './VKLogin.scss';
|
@use './VKLogin.scss';
|
||||||
|
|
||||||
|
.main-containter-wrapper {
|
||||||
|
margin-left: 280px;
|
||||||
|
flex: 1;
|
||||||
|
padding: 30px;
|
||||||
|
background: #f8f9ff;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-containter {
|
||||||
|
max-width: 1920px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@@ -162,3 +175,109 @@
|
|||||||
border-bottom: 1px solid var(--color-gray-200);
|
border-bottom: 1px solid var(--color-gray-200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 280px;
|
||||||
|
background: linear-gradient(180deg, #6366f1 0%, #8b5cf6 100%);
|
||||||
|
padding: 30px 0;
|
||||||
|
position: fixed;
|
||||||
|
height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px 30px;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border-radius: 0 25px 25px 0;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
margin-right: 15px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-link {
|
||||||
|
padding: 12px 50px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-dropdown {
|
||||||
|
.dropdown-arrow {
|
||||||
|
margin-left: auto;
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
.dropdown-arrow {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-menu.expanded {
|
||||||
|
max-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-menu {
|
||||||
|
list-style: none;
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 0.3s ease;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
margin-right: 20px;
|
||||||
|
border-radius: 0 15px 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 30px 40px;
|
||||||
|
color: white;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
||||||
|
border-radius: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
.main-containter-wrapper {
|
|
||||||
margin-left: 280px;
|
|
||||||
flex: 1;
|
|
||||||
padding: 30px;
|
|
||||||
background: #f8f9ff;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-containter {
|
|
||||||
max-width: 1920px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
.sidebar {
|
|
||||||
width: 280px;
|
|
||||||
background: linear-gradient(180deg, #6366f1 0%, #8b5cf6 100%);
|
|
||||||
padding: 30px 0;
|
|
||||||
position: fixed;
|
|
||||||
height: 100vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 15px 30px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all 0.3s;
|
|
||||||
border-radius: 0 25px 25px 0;
|
|
||||||
margin-right: 20px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-weight: 500;
|
|
||||||
text-transform: uppercase;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.15);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin-right: 15px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-link {
|
|
||||||
padding: 12px 50px;
|
|
||||||
font-size: 14px;
|
|
||||||
border-radius: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-dropdown {
|
|
||||||
.dropdown-arrow {
|
|
||||||
margin-left: auto;
|
|
||||||
transition: transform 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.expanded {
|
|
||||||
.dropdown-arrow {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-menu.expanded {
|
|
||||||
max-height: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-menu {
|
|
||||||
list-style: none;
|
|
||||||
max-height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
transition: max-height 0.3s ease;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
margin-right: 20px;
|
|
||||||
border-radius: 0 15px 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 30px 40px;
|
|
||||||
color: white;
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 600;
|
|
||||||
text-transform: uppercase;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-icon {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
|
||||||
border-radius: 15px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
fill: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState, useRef } from 'react';
|
import { useState, useRef } from 'react';
|
||||||
import { fetchFruits } from '@/app/actions/action';
|
|
||||||
import { useClickOutside } from '@/app/hooks/useClickOutside';
|
import { useClickOutside } from '@/app/hooks/useClickOutside';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
@@ -10,7 +9,6 @@ import {IconNotification} from '@/app/ui/icons/icons';
|
|||||||
export default function NotificationsButton() {
|
export default function NotificationsButton() {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [data, setData] = useState<string | null>(null);
|
const [data, setData] = useState<string | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const menuRef = useRef<HTMLDivElement | null>(null);
|
const menuRef = useRef<HTMLDivElement | null>(null);
|
||||||
const t = useTranslations('Global');
|
const t = useTranslations('Global');
|
||||||
@@ -19,24 +17,9 @@ export default function NotificationsButton() {
|
|||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchData = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
setError(null);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await fetchFruits();
|
|
||||||
setData("result");
|
|
||||||
setIsOpen(true);
|
|
||||||
} catch (err) {
|
|
||||||
setError('error message');
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleButtonClick = () => {
|
const handleButtonClick = () => {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
fetchData();
|
setIsOpen(true);
|
||||||
} else {
|
} else {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import style from "@/app/styles/ui.module.scss"
|
|
||||||
|
|
||||||
export default function LogoIcon() {
|
export default function LogoIcon() {
|
||||||
return (
|
return (
|
||||||
<div className={`${style['logo-icon']}`}>
|
<div className="logo-icon">
|
||||||
<svg viewBox="0 0 24 24">
|
<svg viewBox="0 0 24 24">
|
||||||
<path d="M12 2L2 7v10c0 5.55 3.84 9.74 9 11 5.16-1.26 9-5.45 9-11V7l-10-5z"></path>
|
<path d="M12 2L2 7v10c0 5.55 3.84 9.74 9 11 5.16-1.26 9-5.45 9-11V7l-10-5z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
+1
-3
@@ -1,8 +1,6 @@
|
|||||||
import styles from '@/app/styles/ui.module.scss';
|
|
||||||
|
|
||||||
export default function Logo() {
|
export default function Logo() {
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.logo}`}>
|
<div className="logo">
|
||||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||||
<path d="M12 2L2 7v10c0 5.55 3.84 9.74 9 11 5.16-1.26 9-5.45 9-11V7l-10-5z"></path>
|
<path d="M12 2L2 7v10c0 5.55 3.84 9.74 9 11 5.16-1.26 9-5.45 9-11V7l-10-5z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import styles from '@/app/styles/ui.module.scss';
|
|
||||||
import { useState, useRef } from 'react';
|
import { useState, useRef } from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
@@ -32,35 +31,29 @@ export default function DropDownList() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={`
|
className={`nav-dropdown ${dropDownExpanded ? 'expanded' : ''}`}
|
||||||
${styles['nav-dropdown']}
|
|
||||||
${dropDownExpanded ? styles['expanded'] : ''}
|
|
||||||
`}
|
|
||||||
onClick={dropDownHandler}
|
onClick={dropDownHandler}
|
||||||
>
|
>
|
||||||
<div className={`flex ${styles['nav-link']} cursor-pointer select-none`}>
|
<div className="flex nav-link cursor-pointer select-none">
|
||||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||||
<path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2l-5.37.84z"></path>
|
<path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2l-5.37.84z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<p>
|
<p>
|
||||||
{t('marking')}
|
{t('marking')}
|
||||||
</p>
|
</p>
|
||||||
<svg className={`${styles['dropdown-arrow']}`} viewBox="0 0 24 24" fill="currentColor">
|
<svg className="dropdown-arrow" viewBox="0 0 24 24" fill="currentColor">
|
||||||
<path d="M7 10l5 5 5-5z"></path>
|
<path d="M7 10l5 5 5-5z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul className={`
|
<ul className={`sub-menu ${dropDownExpanded ? 'expanded' : ''}`}>
|
||||||
${styles['sub-menu']}
|
|
||||||
${dropDownExpanded ? styles['expanded'] : ''}
|
|
||||||
`}>
|
|
||||||
{links.map((link) => {
|
{links.map((link) => {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
key={link.name}
|
key={link.name}
|
||||||
href={link.href}
|
href={link.href}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
`flex ${styles['nav-link']} ${styles['sub-link']}`,
|
`flex nav-link sub-link`,
|
||||||
{
|
{
|
||||||
'bg-[#5659f1]': pathname === link.href,
|
'bg-[#5659f1]': pathname === link.href,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import styles from '@/app/styles/ui.module.scss'
|
|
||||||
import Logo from '@/app/ui/logo';
|
import Logo from '@/app/ui/logo';
|
||||||
import DropDownList from '@/app/ui/nav-link-dropdown';
|
import DropDownList from '@/app/ui/nav-link-dropdown';
|
||||||
import { logout } from '@/app/actions/auth';
|
import { logout } from '@/app/actions/auth';
|
||||||
@@ -53,14 +52,14 @@ export default function NavLinks() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className=''>
|
<div className=''>
|
||||||
<nav className={`${styles.sidebar}`}>
|
<nav className="sidebar">
|
||||||
<Logo />
|
<Logo />
|
||||||
<ul>
|
<ul>
|
||||||
<Link
|
<Link
|
||||||
key={t('home')}
|
key={t('home')}
|
||||||
href='/pages/dashboard'
|
href='/pages/dashboard'
|
||||||
className={clsx(
|
className={clsx(
|
||||||
`flex ${styles['nav-link']}`,
|
"flex nav-link",
|
||||||
{
|
{
|
||||||
'bg-[#5659f1]': pathname === '/pages/dashboard',
|
'bg-[#5659f1]': pathname === '/pages/dashboard',
|
||||||
},
|
},
|
||||||
@@ -80,7 +79,7 @@ export default function NavLinks() {
|
|||||||
key={link.name}
|
key={link.name}
|
||||||
href={link.href}
|
href={link.href}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
`flex ${styles['nav-link']}`,
|
`flex nav-link`,
|
||||||
{
|
{
|
||||||
'bg-[#5659f1]': pathname === link.href,
|
'bg-[#5659f1]': pathname === link.href,
|
||||||
},
|
},
|
||||||
@@ -96,7 +95,7 @@ export default function NavLinks() {
|
|||||||
<Link
|
<Link
|
||||||
key={t('exit')}
|
key={t('exit')}
|
||||||
href='/login'
|
href='/login'
|
||||||
className={`flex ${styles['nav-link']}`}
|
className="flex nav-link"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
logout();
|
logout();
|
||||||
|
|||||||
Reference in New Issue
Block a user