Skip to content

Commit

Permalink
feature: Add CardProfileTop
Browse files Browse the repository at this point in the history
Start adding basic profile structure including first card profile.

Refs: CU-8696hrm29
Signed-off-by: Jimmy <[email protected]>
  • Loading branch information
JimTheCat committed Nov 11, 2024
1 parent 80ee86d commit fc5782d
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 14 deletions.
23 changes: 23 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@
"@jest/globals": "^29.7.0",
"@testing-library/jest-dom": "^6.6.2",
"@testing-library/react": "^16.0.1",
"@types/dompurify": "^3.0.5",
"@types/jest": "^29.5.13",
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"@types/react-i18next": "^8.1.0",
"@vitejs/plugin-react": "^4.3.2",
"dompurify": "^3.1.7",
"eslint": "^9.11.1",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.12",
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/Components/Cards/ProfileAboutMe/ProfileAboutMe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {Card, Text} from "@mantine/core";
import {InnerHtmlHandler} from "../../InnerHtmlHandler/InnerHtmlHandler.tsx";

export const ProfileAboutMe = (props: { htmlContent: string }) => {
return (
<Card shadow="sm" padding="lg" radius="md" w={500} withBorder>
<Text size={"lg"}>O mnie</Text>
<InnerHtmlHandler innerHtml={props.htmlContent}/>
</Card>
);
}
1 change: 1 addition & 0 deletions frontend/src/Components/Cards/ProfileAboutMe/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ProfileAboutMe'
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {Card, Grid, Group, Image, Text, UnstyledButton} from "@mantine/core";
import {Multimedia} from "../../../Services/Constants/DummyMultimedia.tsx";

export const ProfileMultimedia = (props: { multimedia: Multimedia[] }) => {

const handleButtonClick = (event) => {
event.preventDefault();

window.open(event.target.href, '_blank', 'noopener,noreferrer');
}

return (
<Card shadow="sm" px="lg" pt={"lg"} radius="md" w={400} withBorder>
<Group justify={"space-between"} mb={15}>
<Text size={"lg"}>Multimedia</Text>
<UnstyledButton component="a" href="https://www.google.com" onClick={handleButtonClick} c="dimmed">Wyświetl
wszystko</UnstyledButton>
</Group>

<Grid gutter={"xs"} align={"center"}>
{props.multimedia.map((media, index) => {
return (
<Grid.Col span={4}>
<Image key={index} src={media.url} alt={media.type} w={"auto"} h={100} fit={"contain"}/>
</Grid.Col>
);
})}
</Grid>

</Card>
);
}
1 change: 1 addition & 0 deletions frontend/src/Components/Cards/ProfileMultimedia/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ProfileMultimedia'
32 changes: 23 additions & 9 deletions frontend/src/Components/Cards/ProfileTop/CardProfileTop.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import {Box, Card, Group, Image, Stack, Text} from "@mantine/core";
import {Box, Card, Group, Image, Skeleton, Stack, Text} from "@mantine/core";
import {DummyUserType} from "../../../Services/Constants/DummyUser.tsx";
import {useState} from "react";


export const CardProfileTop = (props: { userDetails: DummyUserType }) => {

const [isProfilePictureLoaded, setIsProfilePictureLoaded] = useState(false);

return (
<Card shadow="sm" padding="lg" radius="md" w={"fit-content"} withBorder>
<Card.Section withBorder>
Expand All @@ -15,14 +19,24 @@ export const CardProfileTop = (props: { userDetails: DummyUserType }) => {

<Box pos={"relative"} top={-35}>
<Group>
<Image
src={props.userDetails.profilePicture}
w={"auto"}
h={120}
fit={"cover"}
radius={180}
bd={"2px solid"}
/>
<Box>
{!isProfilePictureLoaded && (
<Skeleton
circle
height={120}
/>
)}
<Image
src={props.userDetails.profilePicture}
w={"auto"}
h={120}
fit={"cover"}
onLoad={() => setIsProfilePictureLoaded(true)}
radius={180}
bd={"2px solid"}
display={isProfilePictureLoaded ? "block" : "none"}
/>
</Box>
<Stack justify="flex-end" gap={0} mt={"lg"}>
<Group justify={"center"} gap={"xs"} align={"baseline"}>
<Text size={"xl"}>{props.userDetails.name} {props.userDetails.surname}</Text>
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/Components/InnerHtmlHandler/InnerHtmlHandler.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {TypographyStylesProvider} from "@mantine/core";
import DOMPurify from 'dompurify';

export const InnerHtmlHandler = (props: { innerHtml: string }) => {

const allowedArgs = {
//TODO: Define allowed tags and attributes
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'ul', 'li', 'br'],
ALLOWED_ATTR: ['href', 'title'],
}

// Validate innerHtml to prevent XSS
const sanitizedHtml = DOMPurify.sanitize(props.innerHtml);

return (
<TypographyStylesProvider>
<div
dangerouslySetInnerHTML={{__html: sanitizedHtml}}
/>
</TypographyStylesProvider>
);
}
19 changes: 16 additions & 3 deletions frontend/src/Pages/Profile/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import {useParams} from "react-router-dom";
import {DummyUser} from "../../Services/Constants/DummyUser.tsx";
import {CardProfileTop} from "../../Components/Cards/ProfileTop/CardProfileTop.tsx";
import {Box} from "@mantine/core";
import {CardProfileTop} from "../../Components/Cards/ProfileTop";
import {Box, Group, Stack} from "@mantine/core";
import {ProfileAboutMe} from "../../Components/Cards/ProfileAboutMe";
import {ProfileMultimedia} from "../../Components/Cards/ProfileMultimedia";
import {DummyMultimedia} from "../../Services/Constants/DummyMultimedia.tsx";

export const Profile = () => {

Expand All @@ -10,7 +13,17 @@ export const Profile = () => {
if (DummyUser && DummyUser.tag === userTag) {
return (
<Box px={"xl"} py={"xs"}>
<CardProfileTop userDetails={DummyUser}/>
<Group align={"flex-start"} justify={"center"} gap={70}>
<Stack>
<CardProfileTop userDetails={DummyUser}/>
<ProfileAboutMe htmlContent={DummyUser.profileDetails ? DummyUser.profileDetails : ""}/>

{/*Here should be post map*/}
</Stack>
<Stack>
<ProfileMultimedia multimedia={DummyMultimedia}/>
</Stack>
</Group>
</Box>
);
}
Expand Down
23 changes: 23 additions & 0 deletions frontend/src/Services/Constants/DummyMultimedia.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export type Multimedia = {
url: string,
type?: string,
}

export const DummyMultimedia: Multimedia[] = [
{
type: "image",
url: "https://www.w3schools.com/w3images/avatar2.png",
},
{
type: "image",
url: "https://www.w3schools.com/w3images/avatar6.png",
},
{
type: "image",
url: "https://www.w3schools.com/w3images/avatar5.png",
},
{
type: "image",
url: "https://www.w3schools.com/w3images/avatar4.png",
}
]
2 changes: 1 addition & 1 deletion frontend/src/Services/Constants/DummyUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ export const DummyUser: DummyUserType = {
tag: '@johndoe',
pronouns: "he/him",
profilePicture: "https://static-cdn.jtvnw.net/jtv_user_pictures/a7423251-6e4f-42f2-a33f-ca083eafae69-profile_image-300x300.png",
profileDetails: "<h1>Test details</h1>",
profileDetails: "<h4>Test <b>details</b></h4><p>Hello world!</p>",
friends: DummyUserFriends
}
3 changes: 2 additions & 1 deletion frontend/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true
},
"include": ["src"]
}

0 comments on commit fc5782d

Please sign in to comment.