Skip to content

Commit

Permalink
Merge pull request #295 from NIAEFEUP/feature/user-info-page
Browse files Browse the repository at this point in the history
initial user info page
  • Loading branch information
rubuy-74 authored Feb 18, 2025
2 parents 6057ae4 + 21db8ba commit f374913
Show file tree
Hide file tree
Showing 16 changed files with 386 additions and 21 deletions.
File renamed without changes.
File renamed without changes.
31 changes: 31 additions & 0 deletions src/lib/components/buttons/edit-button.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import EditButton from './edit-button.svelte';

export default {
title: 'Atoms/Buttons/Edit Button',
component: EditButton,
parameters: {
layout: 'centered',
controls: { exclude: ['type'] }
}
};

export const SmallEditButton = {
args: {
size: 'small',
link: 'https://lipsum.org'
}
};

export const MediumEditButton = {
args: {
size: 'medium',
link: 'https://lipsum.org'
}
};

export const LargeEditButton = {
args: {
size: 'large',
link: 'https://lipsum.org'
}
};
31 changes: 31 additions & 0 deletions src/lib/components/buttons/edit-button.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts">
import Icon from '@/lib/components/icons/icon.svelte';
import Icons from '@/lib/components/icons/icons';
export let type: 'button' | 'submit' | 'reset' = 'button',
size: keyof typeof sizeList,
link: string;
const sizeList = {
small: 'w-12 h-12',
medium: 'w-20 h-20',
large: 'w-32 h-32'
};
</script>

<a href={link}>
<button
aria-label="Edit"
{type}
class="flex justify-center bg-muted-red-500 hover:bg-muted-red-300 {sizeList[
size
]} min-w-0 rounded px-2 py-2"
>
<div class="flex h-full w-full items-center justify-center">
<Icon
src={Icons.Edit}
size={size == 'small' ? '24px' : size == 'medium' ? '42px' : '62px'}
color="white"
/>
</div>
</button>
</a>
3 changes: 2 additions & 1 deletion src/lib/components/icons/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from 'svelte-icons-pack/fa';
import { BiMap } from 'svelte-icons-pack/bi';
import { IoMail, IoClose, IoEye, IoEyeOff } from 'svelte-icons-pack/io';
import { FiEdit2 } from 'svelte-icons-pack/fi';
import { FiLogOut, FiEdit2 } from 'svelte-icons-pack/fi';

const Icons = {
Instagram: FaBrandsInstagram,
Expand All @@ -26,6 +26,7 @@ const Icons = {
Pin: BiMap,
Visible: IoEye,
Hidden: IoEyeOff,
Logout: FiLogOut,
Edit: FiEdit2
};

Expand Down
13 changes: 3 additions & 10 deletions src/routes/(app)/+error.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,15 @@
import ErrorSection from './_components/error/error-section.svelte';
// @ts-expect-error Import is as expected but throws error
import { page } from '$app/stores';
import Button from '$lib/components/button.svelte';
import Button from '@/lib/components/buttons/button.svelte';
</script>

<main class="mx-10 my-20 flex flex-col justify-center gap-20 font-source_code">
<section class="flex flex-col gap-10 break-normal text-center text-white">
<h1 class="text-7xl font-extrabold 2xl:text-huge">{$page.status}</h1>
<h2 class="text-3xl font-semibold md:text-4xl 2xl:text-6xl">missing ; before statement</h2>
<h2 class="text-3xl font-semibold md:text-4xl 2xl:text-6xl">Error</h2>
</section>
<div class="m-auto flex flex-row gap-20">
<ErrorSection align="text-left" heading="Error type" text="Syntax Error" />
<ErrorSection
align="text-right"
heading="What went wrong?"
text="There is a semicolon (;) missing somewhere"
/>
</div>
<ErrorSection align="text-center" heading="What went wrong?" text={$page.error.message} />
<form class="m-auto" method="GET" action="/">
<Button type="submit" color="primary" hoverColor="secondary" text="Voltar" width="medium" />
</form>
Expand Down
73 changes: 73 additions & 0 deletions src/routes/(app)/error.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Layout } from 'lucide-svelte';
import ErrorPage from './+error.svelte';
import LayoutDecorator from '$lib/storybook-utils/layout-decorator.svelte';

export default {
title: 'Pages/Error',
component: ErrorPage,
parameters: {
layout: 'fullscreen',
backgrounds: { default: 'clear' }
},
decorators: [() => Layout, () => LayoutDecorator]
};

export const NotFound = {
parameters: {
sveltekit_experimental: {
stores: {
page: {
status: 404,
error: {
message: 'User not found'
}
}
}
}
}
};

export const InternalServerError = {
parameters: {
sveltekit_experimental: {
stores: {
page: {
status: 500,
error: {
message: 'Internal server error'
}
}
}
}
}
};

export const Forbidden = {
parameters: {
sveltekit_experimental: {
stores: {
page: {
status: 403,
error: {
message: 'Access forbidden'
}
}
}
}
}
};

export const BadRequest = {
parameters: {
sveltekit_experimental: {
stores: {
page: {
status: 400,
error: {
message: 'Bad request'
}
}
}
}
}
};
14 changes: 7 additions & 7 deletions src/routes/(app)/team/_components/team-member-hexagon.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const MobileHexagon = {
role: 'Co-Gestor de Projetos',
photo: 'images/previews/bruno_rosendo.png',
linkedin: 'https://pt.linkedin.com/',
gitHub: 'https://github.com/',
github: 'https://github.com/',
websites: [{ url: 'https://www.facebook.com/' }]
}
},
Expand Down Expand Up @@ -55,7 +55,7 @@ export const CustomIconHexagon = {
role: 'Co-Gestor de Projetos',
photo: 'images/previews/bruno_rosendo.png',
linkedin: 'https://pt.linkedin.com/',
gitHub: 'https://github.com/',
github: 'https://github.com/',
websites: [{ iconPath: 'images/previews/facebook.png', url: 'https://www.facebook.com/' }]
}
}
Expand All @@ -69,7 +69,7 @@ export const HoveredCustomIconHexagon = {
role: 'Co-Gestor de Projetos',
photo: 'images/previews/bruno_rosendo.png',
linkedin: 'https://pt.linkedin.com/',
gitHub: 'https://github.com/',
github: 'https://github.com/',
websites: [{ iconPath: 'images/previews/facebook.png', url: 'https://www.facebook.com/' }]
}
},
Expand All @@ -86,7 +86,7 @@ export const DefaultIconHexagon = {
role: 'Co-Gestor de Projetos',
photo: 'images/previews/bruno_rosendo.png',
linkedin: 'https://pt.linkedin.com/',
gitHub: 'https://github.com/',
github: 'https://github.com/',
websites: [{ url: 'https://www.facebook.com/' }]
}
}
Expand All @@ -100,7 +100,7 @@ export const HoveredDefaultIconHexagon = {
role: 'Co-Gestor de Projetos',
photo: 'images/previews/bruno_rosendo.png',
linkedin: 'https://pt.linkedin.com/',
gitHub: 'https://github.com/',
github: 'https://github.com/',
websites: [{ url: 'https://www.facebook.com/' }]
}
},
Expand All @@ -116,7 +116,7 @@ export const DefaultProfilePicHexagon = {
email: '[email protected]',
role: 'Co-Gestor de Projetos',
linkedin: 'https://pt.linkedin.com/',
gitHub: 'https://github.com/',
github: 'https://github.com/',
websites: [{ url: 'https://www.facebook.com/' }]
}
}
Expand All @@ -129,7 +129,7 @@ export const HoveredDefaultProfilePicHexagon = {
email: '[email protected]',
role: 'Co-Gestor de Projetos',
linkedin: 'https://pt.linkedin.com/',
gitHub: 'https://github.com/',
github: 'https://github.com/',
websites: [{ url: 'https://www.facebook.com/' }]
}
},
Expand Down
4 changes: 2 additions & 2 deletions src/routes/(app)/team/_components/team-member-hexagon.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@
<Icon src={Icons.Linkedin} color="white" size="100%" /></a
>
{/if}
{#if teamMember.gitHub}
{#if teamMember.github}
<a
href={teamMember.gitHub}
href={teamMember.github}
class="full-opacity h-6 opacity-0 transition-all duration-500 ease-out group-hover:static group-hover:opacity-100 sm:h-6 md:h-7 lg:h-8 xl:h-9"
aria-label="{teamMember.name}'s GitHub"
><Icon src={Icons.Github} color="white" size="100%" /></a
Expand Down
97 changes: 97 additions & 0 deletions src/routes/(app)/user/[id]/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script lang="ts">
import SocialMediaIcon from '../_components/social-media-icon.svelte';
import IsActiveBadge from '../_components/is-active-badge.svelte';
import type { PageData } from './$types';
import type { TeamMember } from '@/types/team-member';
import Icon from '@/lib/components/icons/icon.svelte';
import Icons from '@/lib/components/icons/icons';
import EditButton from '$lib/components/buttons/edit-button.svelte';
import { goto } from '$app/navigation';
export let data: PageData;
export let teamMember: TeamMember = data.teamMember;
async function logout() {
const response = await fetch('/api/auth/logout', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (response.ok) {
goto('/');
}
}
</script>

{#await teamMember}
<!-- TODO: include a waiting animation -->
<p>...waiting</p>
{:then teamMember}
<section>
<div class="flex w-full justify-center px-4 sm:px-6 lg:px-8">
<div class="flex w-4/5 flex-col content-center gap-y-4 md:gap-y-6 lg:w-3/4 xl:w-1/2">
<div class="flex h-12 justify-end gap-x-3 lg:h-10 xl:h-12">
<EditButton size="small" link="https://lipsum.com" />
<button
class="w-12 rounded-md bg-muted-red-500 p-3 lg:w-12 xl:w-12"
on:click={() => logout()}
>
<Icon src={Icons.Logout} color="white" size="100%" />
</button>
</div>
<div class="flex flex-col items-center gap-6 sm:flex-row sm:items-start">
<img
src={teamMember.photo ? teamMember.photo : '/images/default_profile_pic.png'}
alt="User pic"
class="h-32 w-32 rounded-lg sm:h-52 sm:w-52"
/>
<div class="flex flex-grow flex-col">
<div class="mb-5 flex flex-col items-center gap-3 sm:flex-row sm:gap-6">
<h3 class="text-2xl font-bold lg:text-lg xl:text-xl 2xl:text-2xl">
{teamMember.name}
</h3>
<IsActiveBadge {teamMember} />
</div>
{#if teamMember.bio}
<p
class="text-md lg:text-md mb-6 text-center sm:text-left sm:text-base xl:text-lg 2xl:text-xl"
>
{teamMember.bio}
</p>
{/if}
<div class="flex justify-center gap-3 sm:justify-start">
{#if teamMember.github}
<SocialMediaIcon
url={teamMember.github}
social={'Github'}
icon={Icons.Github}
user={teamMember.name}
/>
{/if}
{#if teamMember.linkedin}
<SocialMediaIcon
url={teamMember.linkedin}
social={'Linkedin'}
icon={Icons.Linkedin}
user={teamMember.name}
/>
{/if}
{#if teamMember.websites}
{#each teamMember.websites as customWebsite}
<SocialMediaIcon
url={customWebsite.url}
social="custom website"
icon={Icons.Globe}
user={teamMember.name}
iconPath={customWebsite.iconPath}
/>
{/each}
{/if}
</div>
</div>
</div>
</div>
</div>
</section>
{/await}
11 changes: 11 additions & 0 deletions src/routes/(app)/user/[id]/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types';

export const load: PageLoad = async ({ fetch, params }) => {
const res = await fetch(`/api/accounts/${params.id}`);
if (!res.ok) error(res.status, 'User not found');

const teamMember = await res.json();

return { teamMember };
};
Loading

0 comments on commit f374913

Please sign in to comment.