Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/imp/upload-profile-image #52

Merged
merged 19 commits into from
Oct 4, 2024
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts


package-lock.json
pnpm-lock.yaml
5 changes: 3 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const withNextIntl = require('next-intl/plugin')();
const nextConfig = {
images: {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'https://picsum.photos',
port: '443'
}
]
],
domains: ['localhost']
}
};

Expand Down
6,436 changes: 4,160 additions & 2,276 deletions package-lock.json

Large diffs are not rendered by default.

628 changes: 344 additions & 284 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion src/config/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export interface Env {
apiWithCredentials: string | undefined;
apiBase: string | undefined;
urlFront: string | undefined;
urlFile: string | undefined;
publicBucket: string | undefined;
privateBucket: string | undefined;
[key: string]: string | undefined;
}

Expand All @@ -20,7 +23,10 @@ export const env: Env = {
apiPort: process.env.NEXT_PUBLIC_API_PORT,
apiWithCredentials: process.env.NEXT_PUBLIC_API_WITH_CREDENTIALS,
apiBase: process.env.NEXT_PUBLIC_API_BASE,
urlFront: process.env.NEXT_PUBLIC_URL_FRONT
urlFront: process.env.NEXT_PUBLIC_URL_FRONT,
urlFile: process.env.NEXT_PUBLIC_URL_FILE,
publicBucket: process.env.NEXT_PUBLIC_PUBLIC_BUCKET,
privateBucket: process.env.NEXT_PUBLIC_PRIVATE_BUCKET
};

export const validateEnv = () => {
Expand Down
1 change: 1 addition & 0 deletions src/features/auth/recovery-code/organisms/recoveryCode.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use client';
import React from 'react';
import style from './recovery-code.module.css';
import { InputForm, InputType } from '@/features/shared/atoms/inputForm/InputForm';
Expand Down
31 changes: 21 additions & 10 deletions src/features/navbar/molecules/dropdown/DropdownUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ type Props = {
isUserDropdownOpen: boolean;
handleDropdownUser: () => void;
id?:string;
user?: {
phone: string | null;
email: string | null;
last_name: string | null;
first_name: string | null;
id: string;
image_id: string | null;
};
}

export const DropdownUser = (props: Props) => {
Expand All @@ -60,8 +68,8 @@ export const DropdownUser = (props: Props) => {
<div className={style.container}>
<div className={style.containerIconUser}>
<button onClick={props.handleDropdownUser} className={`${style.iconUser} ${background}`}>
<Image src={props.dataUser.image} alt={'Icon user'} height={1920} width={1080}/>
<Image className={`${style.dropdown} ${rotate}`} src={props.dataUser.icon} alt={'dropdown'}/>
<Image src={props.user?.image_id ?? props.dataUser.image} alt={'Icon user'} height={1080} width={1080}/>
<Image className={`${style.dropdown} ${rotate}`} width={82} height={82} src={props.user?.image_id ?? props.dataUser.icon} alt={'dropdown'}/>
</button>
</div>
<motion.ul
Expand All @@ -72,33 +80,36 @@ export const DropdownUser = (props: Props) => {
>
<div className={style.perfil}>
<div className={style.containerIconUserOpen}>
<Image className={style.iconUserOpen} src={props.dataUser.image} alt={'Icon user'} height={1920}
width={1080}/>
<p>{props.dataUser.username}</p>
<Image className={style.profileImage} src={props.user?.image_id ?? props.dataUser.image}
alt={'Icon user'} width={82} height={82}/>
<p>{props.user?.first_name ?? props.dataUser.username}</p>
</div>
{
props.dataPerfil.map(({ description, path }) =>
<Link href={path ?? '#'} key={t(description)} className={style.perfilSections}>
{path === '/profile' ? <IoPersonOutline /> : <IoSettingsOutline />}
{path === '/profile' ? <IoPersonOutline/> : <IoSettingsOutline/>}
<p>{t(description)}</p>
</Link>
)
}
<AccordionComponent key={props.id ?? '1'}
className={{ accordion:style.langResponsive }} accordionItemsProps={{
className={{ accordion: style.langResponsive }} accordionItemsProps={{
ariaLabel: 'Accordion 1',
title: <div className={style.langResponsiveTitle}><MdLanguage/>Idiomas</div>
}}
accordionItems={[
<>
<div
className={style.perfilSections}>
<Link className={'ml-1 rounded p-1 text-white'} href={`${pathName}?${paramsString}`}
<Link className={'ml-1 rounded p-1 text-white'}
href={`${pathName}?${paramsString}`}
locale={'es'}>Español <Image src={IconFlagSpain} alt="flag spain"/></Link>
</div>
<div className={style.perfilSections}>
<Link className={'ml-1 rounded p-1 text-white'} href={`${pathName}?${paramsString}`}
locale={'en'}>Ingles <Image src={IconFlagUsa} alt="flag usa"/></Link>
<Link className={'ml-1 rounded p-1 text-white'}
href={`${pathName}?${paramsString}`}
locale={'en'}>Ingles <Image src={IconFlagUsa}
alt="flag usa"/></Link>
</div>
</>
]}/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
.iconUser .dropdown{
@apply absolute centerAlign left-[300px] w-6 h-6 m-0
}

.profileImage{
@apply max-w-[56px] w-14 h-12 rounded-[50%] object-cover pr-1
}
.iconUser img {
@apply rounded-full w-10 h-10 m-auto transition-all;
}
Expand Down
11 changes: 10 additions & 1 deletion src/features/navbar/organisms/NavbarTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ import { dataLogin, dataPerfil, dataUser } from '@/features/navbar/constants/dat
import { DropdownUser } from '@/features/navbar/molecules/dropdown/DropdownUser';

type Props = {
isPublic: boolean;
isPublic: boolean;
user?: {
phone: string | null;
email: string | null;
last_name: string | null;
first_name: string | null;
id: string;
image_id: string | null;
};
}

export const NavbarTop = (props: Props) => {
Expand Down Expand Up @@ -41,6 +49,7 @@ export const NavbarTop = (props: Props) => {
handleDropdownLang={handleDropdownLang}
/>
<DropdownUser dataPerfil={dataPerfil}
user={props.user}
style={style} dataUser={dataUser}
dataLogin={dataLogin}
isUserDropdownOpen={isUserDropdownOpen}
Expand Down
6 changes: 4 additions & 2 deletions src/features/navbar/template/NavbarTopTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react';
import { NavbarTop } from '@/features/navbar/organisms/NavbarTop';
import { getUser } from '@/features/profile/actions/ProfileAction';

type Props = {
isPublic: boolean;
}

export const NavbarTopTemplate = (props: Props) => {
export const NavbarTopTemplate = async(props: Props) => {
const user = await getUser();
return (
<NavbarTop isPublic={props.isPublic} />
<NavbarTop isPublic={props.isPublic} user={user} />
);
};
61 changes: 59 additions & 2 deletions src/features/profile/actions/ProfileAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@
import { cookies } from 'next/headers';
import { createClient } from '@/lib/server/server';
import { redirect, RedirectType } from 'next/navigation';
import { handleGetFile } from '@/features/shared/actions/fileAction';
import { env } from '@/config/api';

export const getUser = async() => {
interface User {
id: string;
image_id: string | null;
phone: string | null;
email: string | null;
last_name: string | null;
first_name: string | null;
}

const getCookies = () => {
const cookieStore = cookies();
const supabase = createClient(cookieStore);
return createClient(cookieStore);
};

const getSession = async() => {
const supabase = getCookies();

const { data, error } = await supabase.auth.getSession();
const user = data?.session?.user;

if (error) {
throw new Error('Error at getting the user', error);
}
Expand All @@ -18,3 +34,44 @@ export const getUser = async() => {
return user;
}
};

export const getUser = async() => {
const supabase = getCookies();

const user = await getSession();

if (!user) {
redirect('/auth/login', RedirectType.push);
}

const { data, error } = await supabase.from('profiles').select().eq('id', user?.id);

if (error) {
MiaPass marked this conversation as resolved.
Show resolved Hide resolved
throw new Error('Error at getting the user');
}

let image = data[0]?.image_id ?? null;
if (image){
image = await handleGetFile(image);
image = `${env.urlFile}/${image?.isPublic ? env.publicBucket : env.privateBucket}/data/${image?.path}`;
}

const userComplete: User = {
id: user.id,
image_id: image,
phone: user.phone ?? null,
email: user.email ?? null,
last_name: data[0]?.last_name,
first_name: data[0]?.first_name
};

return userComplete;
};

export const uploadUser = async(image_id: string| null | undefined, id: string) => {
MiaPass marked this conversation as resolved.
Show resolved Hide resolved
const supabase = getCookies();

await supabase.from('profiles').update({ image_id }).eq('id', id);

redirect('/dashboard', RedirectType.push);
};
9 changes: 6 additions & 3 deletions src/features/profile/organisms/profile.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
.containerList div{
@apply grid grid-cols-1 gap-1 w-full
}
.containerList p{

.hiddenInput{
@apply hidden w-0 h-0 invisible
}
.infoUser{
@apply !text-white !text-left font-normal px-4 py-2 rounded-[8px] bg-bgInputDisabled border-2 border-borderInput
Expand All @@ -71,6 +71,9 @@
.containerImg{
@apply relative !flex flex-col justify-center items-center gap-4 mx-auto
}
.profileImage{
@apply w-20 h-20 rounded-[100px]
}
.pencil {
@apply absolute;
bottom: 50%;
Expand Down Expand Up @@ -123,4 +126,4 @@
@screen xl{
}
@screen 2xl{
}
}
Loading
Loading