Skip to content

Commit

Permalink
[Web] Refactor/sidebar (#3361)
Browse files Browse the repository at this point in the history
* refactor(web): [Sidebar] improve sidebar, styles, add form and workspace switter

* refactor(web): [Sidebar] fix broken spaces

* feat(web): [Subscribe] add subscription user email

* fix: spelling errors
  • Loading branch information
NdekoCode authored Nov 21, 2024
1 parent f58fdc1 commit 74bdec5
Show file tree
Hide file tree
Showing 29 changed files with 1,997 additions and 1,706 deletions.
7 changes: 6 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"words": [
" X",
" X ",
"hookform",
"accepte",
"Accordian",
"adipiscing",
Expand All @@ -24,6 +25,7 @@
"apidemodt",
"apidemodts",
"apidev",
"apikey",
"apisauce",
"apistage",
"apistagecivo",
Expand Down Expand Up @@ -92,6 +94,7 @@
"creatoe",
"dailyplan",
"Darkmode",
"DATACENTER",
"datas",
"dataToDisplay",
"daygrid",
Expand Down Expand Up @@ -240,6 +243,7 @@
"longpress",
"Lorem",
"lucide",
"mailchimp",
"mainconfig",
"mappagination",
"mathieudutour",
Expand Down Expand Up @@ -355,7 +359,6 @@
"tailess",
"Tailess",
"tailwindcss",
"timesheet-viewMode",
"tanstack",
"taskid",
"taskstatus",
Expand All @@ -367,6 +370,7 @@
"testid",
"timegrid",
"Timesheet",
"timesheet-viewMode",
"Timesheets",
"Timeslot",
"tinvitations",
Expand Down Expand Up @@ -400,6 +404,7 @@
"VERSONS",
"vertificalline",
"vhidden",
"Waitlist",
"WARNING️",
"wasabisys",
"webm",
Expand Down
4 changes: 4 additions & 0 deletions apps/web/.env
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,7 @@ NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
# Warning: IF TRUE This allows production builds to successfully complete even if
# your project has ESLint errors.
NEXT_IGNORE_ESLINT_ERROR_ON_BUILD=true

# Mailchimp
MAILCHIMP_API_KEY=
MAILCHIMP_LIST_ID=
4 changes: 4 additions & 0 deletions apps/web/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,7 @@ MEET_JWT_APP_SECRET=
# Warning: IF TRUE This allows production builds to successfully complete even if
# your project has ESLint errors.
NEXT_IGNORE_ESLINT_ERROR_ON_BUILD=true

# Mailchimp
MAILCHIMP_API_KEY=
MAILCHIMP_LIST_ID=
2 changes: 1 addition & 1 deletion apps/web/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-mixed-spaces-and-tabs */
'use client';
import 'react-loading-skeleton/dist/skeleton.css';
import '../../styles/globals.css';
import '@/styles/globals.css';

import clsx from 'clsx';
import { Provider } from 'jotai';
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/[locale]/page-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ function MainPage() {
showTimer={headerSize <= 11.8 && isTrackingEnabled}
className="h-full"
mainHeaderSlot={
<div className="sticky z-40 bg-white dark:bg-dark-high">
<div className="bg-white dark:bg-dark-high">
<div className={clsxm('bg-white dark:bg-dark-high ', !fullWidth && 'x-container')}>
<div className="mx-8-container mt-7 !px-0 flex flex-row items-start justify-between ">
<div className="mx-8-container my-3 !px-0 flex flex-row items-start justify-between ">
<div className="flex items-center justify-center h-10 gap-8">
<PeoplesIcon className="text-dark dark:text-[#6b7280] h-6 w-6" />

Expand Down
67 changes: 67 additions & 0 deletions apps/web/app/api/subscribe/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { NextRequest, NextResponse } from 'next/server';

export const POST = async (req: NextRequest) => {
// 1. Destructure the email address from the request body.
const reqData = (await req.json()) as {
email_address: string;
tags: string[];
captcha?: string;
};

if (!reqData.email_address) {
// 2. Throw an error if an email wasn't provided.
return NextResponse.json({ error: 'Email is required' }, { status: 400 });
}

if (!reqData.captcha) {
// 2. Display an error if the captcha code wasn't provided.
console.error('ERROR: Please provide required fields', 'STATUS: 400');
}

try {
// 3. Fetch the environment variables.
const LIST_ID = process.env.MAILCHIMP_LIST_ID;
const API_KEY = process.env.MAILCHIMP_API_KEY ? process.env.MAILCHIMP_API_KEY : '';
if (!LIST_ID || !API_KEY) {
throw new Error('Missing Mailchimp environment variables');
}
// 4. API keys are in the form <key>-us3.
const DATACENTER = API_KEY.split('-')[1];
const mailchimpData = {
email_address: reqData.email_address,
status: 'subscribed',
tags: reqData.tags ? [...reqData.tags] : ['Ever Teams']
};
// 5. Send a POST request to Mailchimp.
const response = await fetch(`https://${DATACENTER}.api.mailchimp.com/3.0/lists/${LIST_ID}/members`, {
body: JSON.stringify(mailchimpData),
headers: {
Authorization: `apikey ${API_KEY}`,
'Content-Type': 'application/json'
},
method: 'POST'
});
console.log(response);
// 6. Swallow any errors from Mailchimp and return a better error message.
if (response.status >= 400) {
const errorResponse = await response.json();
return NextResponse.json(
{
error: `There was an error subscribing to the newsletter: ${errorResponse.detail}`
},
{ status: 400 }
);
}

// 7. If we made it this far, it was a success! 🎉
return NextResponse.json({ error: '', resp: response }, { status: 201 });
} catch (error) {
return NextResponse.json(
{
error: (error as Error).message || (error as Error).toString(),
resp: null
},
{ status: 500 }
);
}
};
132 changes: 69 additions & 63 deletions apps/web/components/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,36 @@ import {
MonitorSmartphone,
LayoutDashboard,
Heart,
FolderKanban,
SquareActivity,
PlusIcon,
Files,
X
X,
Command,
AudioWaveform,
GalleryVerticalEnd
} from 'lucide-react';

import { EverTeamsLogo, SymbolAppLogo } from '@/lib/components/svgs';
import { NavMain } from '@/components/nav-main';
import {
Sidebar,
SidebarContent,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarRail,
SidebarTrigger,
useSidebar,
SidebarMenuSubButton
SidebarMenuSubButton,
SidebarFooter
} from '@/components/ui/sidebar';
import Link from 'next/link';
import { cn } from '@/lib/utils';
import { useOrganizationAndTeamManagers } from '@/app/hooks/features/useOrganizationTeamManagers';
import { useAuthenticateUser, useModal, useOrganizationTeams } from '@/app/hooks';
import { useFavoritesTask } from '@/app/hooks/features/useFavoritesTask';
import { Button } from '@/lib/components/button';
import { CreateTeamModal, TaskIssueStatus } from '@/lib/features';
import { useTranslations } from 'next-intl';
import { WorkspacesSwitcher } from './workspace-switcher';
import { SidebarOptInForm } from './sidebar-opt-in-form';
import { NavProjects } from './nav-projects';
type AppSidebarProps = React.ComponentProps<typeof Sidebar> & { publicTeam: boolean | undefined };
export function AppSidebar({ publicTeam, ...props }: AppSidebarProps) {
const { userManagedTeams } = useOrganizationAndTeamManagers();
const { user } = useAuthenticateUser();
const username = user?.name || user?.firstName || user?.lastName || user?.username;
const { isTeamManager } = useOrganizationTeams();
Expand All @@ -44,11 +42,57 @@ export function AppSidebar({ publicTeam, ...props }: AppSidebarProps) {
const t = useTranslations();
// This is sample data.
const data = {
user: {
name: 'evereq',
email: '[email protected]',
avatar: '/assets/svg/profile.svg'
},
workspaces: [
{
name: 'Ever Teams',
logo: ({ className }: { className?: string }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={25}
height={26}
viewBox="0 0 25 26"
fill="none"
className={cn('size-5', className)}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M.55 18.186l.325-.773 2.04-4.855-.007-.012-1.555-3.127-.167 6.846-.437-.01.173-7.14.283.006-.463-.93-.376-.756.814-.222 4.758-1.298L8.187.935l.348-.773.688.494.805.579.055-.27 7.701 1.565-.057.283 1.34-.367.915-.25-.039.947-.049 1.188.262-.13 3.286 6.604-.392.195-3.168-6.366-.164 4.005 4.177 3.116.701.524-.67.563-4.023 3.38v.003l-.018.015-.123 4.096 3.26-6.716.395.191-3.43 7.063-.238-.116-.03.997-.024.822-.806-.163-5.184-1.047-3.92 3.117-.67.533-.383-.767-.497-.999-.249.317-5.856-4.61.27-.344L8.2 23.177 6.324 19.41 1.37 18.36l-.82-.173zM13.743 3.905L10.35 1.466 17.408 2.9l-3.666 1.005zM2.479 17.177l1.25-2.98 1.806 3.627-3.056-.647zm4.788 1.015l.018.036 6.066 1.617 5.147-4.258-.17-6.256-.025-.018.002-.051-4.86-3.844-6.516 1.67-2.484 5.433 2.821 5.67zm2.325 4.673l-1.484-2.982 3.92 1.045-2.436 1.937zm8.766-1.973l-3.293-.665 3.397-2.81-.104 3.475zm4.005-8.549l-2.508 2.108-.111-4.063 2.62 1.955zM18.52 4.034l-.144 3.515-3.264-2.581 3.408-.934zM9.102 2.277l2.894 2.08-4.335 1.111 1.441-3.19zM2.359 8.33l2.83-.773-1.539 3.367L2.36 8.33zm-.087-1.78l5.134-4.742-.297-.322-5.134 4.742.297.322zm15.641 16.259l-6.936 1.61-.099-.426 6.936-1.61.1.426z"
fill="url(#paint0_linear_11058_107682)"
/>
<defs>
<linearGradient
id="paint0_linear_11058_107682"
x1="-2.65811"
y1="11.7373"
x2="11.928"
y2="4.38343"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D24F39" />
<stop offset={1} stopColor="#791EEC" />
</linearGradient>
</defs>
</svg>
),
plan: 'Enterprise'
},
{
name: 'Ever Gauzy',
logo: AudioWaveform,
plan: 'Startup'
},
{
name: 'Ever Cloc',
logo: GalleryVerticalEnd,
plan: 'Free'
},
{
name: 'Ever Rec',
logo: Command,
plan: 'Free'
}
],
navMain: [
{
title: t('sidebar.DASHBOARD'),
Expand Down Expand Up @@ -138,35 +182,6 @@ export function AppSidebar({ publicTeam, ...props }: AppSidebarProps) {
}
]
},
...(userManagedTeams && userManagedTeams.length > 0
? [
{
title: t('sidebar.PROJECTS'),
label: 'projects',
url: '#',
icon: FolderKanban,
items: [
{
title: t('common.NO_PROJECT'),
label: 'no-project',
url: '#',
component: (
<SidebarMenuSubButton asChild>
<Button
className="w-full text-xs mt-3 dark:text-white rounded-xl border-[0.0938rem]"
variant="outline"
disabled={!user?.isEmailVerified}
>
<PlusIcon className="w-4 h-4" />
{t('common.CREATE_PROJECT')}
</Button>
</SidebarMenuSubButton>
)
}
]
}
]
: []),
{
title: t('sidebar.MY_WORKS'),
url: '#',
Expand Down Expand Up @@ -232,7 +247,8 @@ export function AppSidebar({ publicTeam, ...props }: AppSidebarProps) {
}
]
: [])
]
],
projects: []
};

return (
Expand All @@ -245,30 +261,20 @@ export function AppSidebar({ publicTeam, ...props }: AppSidebarProps) {
<SidebarTrigger
className={cn(
state === 'collapsed' ? 'right-[-20%]' : ' right-[-5%]',
'absolute top-[10.5%] size-7 !bg-[#1C75FD] flex items-center justify-center !rounded-full transition-all duration-300 filter drop-shadow-[0px_0px_6px_rgba(28,117,253,0.30)] z-[55]'
'absolute top-[8%] size-7 !bg-[#1C75FD] flex items-center justify-center !rounded-full transition-all duration-300 filter drop-shadow-[0px_0px_6px_rgba(28,117,253,0.30)] z-[55]'
)}
/>
<SidebarHeader className={cn('mb-[1.4rem]', state === 'collapsed' ? 'items-center' : '')}>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
className={cn(state === 'collapsed' ? 'items-center justify-center' : '')}
size="lg"
asChild
>
<Link href="/">
<div className="flex items-center justify-center rounded-lg aspect-square size-8 text-sidebar-primary-foreground">
<SymbolAppLogo className="size-5" />
</div>
{state === 'expanded' && <EverTeamsLogo dash />}
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
<WorkspacesSwitcher workspaces={data.workspaces} />
</SidebarHeader>
<SidebarContent>
<NavMain items={data.navMain} />
<NavProjects projects={data.projects} />
</SidebarContent>

<SidebarFooter className="p-1 mt-auto">
<SidebarOptInForm />
</SidebarFooter>
<SidebarRail />
</Sidebar>

Expand Down
Loading

0 comments on commit 74bdec5

Please sign in to comment.