Skip to content

Commit c3c0997

Browse files
authored
Merge pull request #13 from RJihyeon/fe/create-profile-page
Fe/create profile page
2 parents 11df4fc + 4ce4e16 commit c3c0997

File tree

11 files changed

+257
-89
lines changed

11 files changed

+257
-89
lines changed

frontend/components/common/TitleDivider.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default function TitleDivider({ title }: TitleDividerProps) {
1010
<div className={"wrapper"}>
1111
<h2>{title}</h2>
1212
</div>
13-
<hr className={"border-1 bg-black"} />
13+
<hr className={"border-1 bg-black mb-4"} />
1414
</section>
1515
);
1616
}

frontend/components/header.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const Header = () => {
1111
}
1212
>
1313
<div className={"bg-slate-800"}>
14-
<div className="w-full lg:w-[70%] max-w-[1300px] flex flex-row justify-between mx-auto">
14+
<div className="wrapper flex flex-row justify-between mx-auto">
1515
<div className={"m-4"}>
1616
<h2>Santa Tell Me</h2>
1717
</div>
@@ -24,7 +24,7 @@ const Header = () => {
2424
<a href="/send">Send</a>
2525
</li>
2626
<li>
27-
<a href="/credits">Credits</a>
27+
<a href="/my">Profile</a>
2828
</li>
2929
</ul>
3030
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { JSX } from "preact";
2+
import { useState } from "preact/hooks";
3+
4+
export default function ProfileBadge() {
5+
return (
6+
<div className={"mx-4 h-full"}>
7+
<h3 className={"hidden"}>Profile badge</h3>
8+
<div
9+
className={
10+
"p-4 bg-gradient-to-br from-red-400 to-slate-200 rounded-lg lg:w-[40vh] h-full"
11+
}
12+
>
13+
<div className={"w-[150px]"}>
14+
<img
15+
src="https://via.placeholder.com/150"
16+
alt="Avatar"
17+
className={"rounded-full border-spacing-2 border-white border-4"}
18+
/>
19+
</div>
20+
<div className={"flex flex-col place-content-between p-4"}>
21+
<span>
22+
<strong>Name:</strong> John Doe
23+
</span>
24+
<span>
25+
<strong>Nickname:</strong> Johnny
26+
</span>
27+
<span>
28+
<strong>Email:</strong> [email protected]
29+
</span>
30+
</div>
31+
</div>
32+
</div>
33+
);
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// src/profile/SectionInbox.tsx
2+
import { JSX } from "preact";
3+
import Inbox from "../../islands/Inbox.tsx";
4+
5+
const SectionInbox = () => {
6+
return (
7+
<section>
8+
<div className={"wrapper"}>
9+
<Inbox />
10+
</div>
11+
</section>
12+
);
13+
};
14+
15+
export default SectionInbox;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// src/profile/SectionProfile.tsx
2+
import { JSX } from "preact";
3+
import ProfileHighlight from "./profile-desc.tsx";
4+
import ProfileBadge from "./ProfileBadge.tsx";
5+
import ProfileEdit from "../../islands/ProfileEdit.tsx";
6+
7+
const SectionProfile = () => {
8+
return (
9+
<section>
10+
<div className={"wrapper h-[350px]"}>
11+
<ProfileBadge />
12+
<div className={"flex flex-col gap-4 w-full mr-4"}>
13+
<ProfileHighlight />
14+
<ProfileEdit />
15+
</div>
16+
</div>
17+
</section>
18+
);
19+
};
20+
21+
export default SectionProfile;
+27-72
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,28 @@
1-
import { JSX } from "preact";
1+
import { JSX } from "preact";
22

3-
export default function Profile() {
4-
return (
5-
<div style={styles.container}>
6-
<div style={styles.avatarContainer}>
7-
<img
8-
src="https://via.placeholder.com/150"
9-
alt="Avatar"
10-
style={styles.avatar}
11-
/>
12-
</div>
13-
<div style={styles.detailsContainer}>
14-
<div style={styles.field}>
15-
<strong>Name:</strong> John Doe
16-
</div>
17-
<div style={styles.field}>
18-
<strong>Nickname:</strong> Johnny
19-
</div>
20-
<div style={styles.field}>
21-
<strong>Kakao:</strong> <a href="https://kakao.com/johndoe">Profile Link</a>
22-
</div>
23-
<div style={styles.field}>
24-
<strong>Email:</strong> [email protected]
25-
</div>
26-
<div style={styles.field}>
27-
<strong>Password:</strong> ••••••••
28-
</div>
29-
</div>
30-
<button style={styles.editButton}>Edit Profile</button>
31-
</div>
32-
);
33-
}
34-
35-
const styles = {
36-
container: {
37-
display: 'flex',
38-
alignItems: 'center',
39-
justifyContent: 'space-between',
40-
padding: '20px',
41-
border: '1px solid #ccc',
42-
borderRadius: '8px',
43-
maxWidth: '600px',
44-
margin: 'auto',
45-
position: 'relative',
46-
},
47-
avatarContainer: {
48-
flexShrink: 0,
49-
},
50-
avatar: {
51-
width: '150px',
52-
height: '150px',
53-
borderRadius: '50%',
54-
},
55-
detailsContainer: {
56-
flexGrow: 1,
57-
marginLeft: '20px',
58-
},
59-
field: {
60-
marginBottom: '10px',
61-
},
62-
editButton: {
63-
position: 'absolute',
64-
bottom: '10px',
65-
right: '10px',
66-
padding: '8px 16px',
67-
backgroundColor: '#007bff',
68-
color: '#fff',
69-
border: 'none',
70-
borderRadius: '4px',
71-
cursor: 'pointer',
72-
},
73-
};
3+
export default function ProfileHighlight() {
4+
return (
5+
<>
6+
<h3 className={"hidden"}>My Profile</h3>
7+
<div
8+
className={"flex flex-row flex-wrap gap-2 bg-red-400 rounded-lg p-4"}
9+
>
10+
<div className={"w-full"}>
11+
<div className={"flex flex-row gap-2 my-2 text-white"}>
12+
<div>
13+
<a href="https://kakao.com/johndoe">
14+
<span>Kakao Profile</span>
15+
</a>
16+
</div>
17+
<div>
18+
<span>Total guesses: 0</span>
19+
</div>
20+
<div>
21+
<span>Correct %: 100%</span>
22+
</div>
23+
</div>
24+
</div>
25+
</div>
26+
</>
27+
);
28+
}

frontend/fresh.gen.ts

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import * as $send_index from "./routes/send/index.tsx";
1010
import * as $testcookie_index from "./routes/testcookie/index.tsx";
1111
import * as $Counter from "./islands/Counter.tsx";
1212
import * as $DropdownListForm from "./islands/DropdownListForm.tsx";
13+
import * as $Inbox from "./islands/Inbox.tsx";
14+
import * as $ProfileEdit from "./islands/ProfileEdit.tsx";
1315
import * as $uploadResult from "./islands/uploadResult.tsx";
1416
import type { Manifest } from "$fresh/server.ts";
1517

@@ -25,6 +27,8 @@ const manifest = {
2527
islands: {
2628
"./islands/Counter.tsx": $Counter,
2729
"./islands/DropdownListForm.tsx": $DropdownListForm,
30+
"./islands/Inbox.tsx": $Inbox,
31+
"./islands/ProfileEdit.tsx": $ProfileEdit,
2832
"./islands/uploadResult.tsx": $uploadResult,
2933
},
3034
baseUrl: import.meta.url,

frontend/islands/Inbox.tsx

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { JSX } from "preact";
2+
import { useState } from "preact/hooks";
3+
4+
interface Recording {
5+
id: number;
6+
sender: string;
7+
receiveTime: string;
8+
guessed: boolean;
9+
}
10+
11+
export default function Inbox() {
12+
const [recordings, setRecordings] = useState<Recording[]>([
13+
{ id: 1, sender: "Alice", receiveTime: "2024-11-25 10:00", guessed: false },
14+
{ id: 2, sender: "Bob", receiveTime: "2024-11-25 11:00", guessed: true },
15+
// Add more recordings as needed
16+
]);
17+
18+
const handleGuess = (id: number) => {
19+
console.log(`Guessing for recording ID: ${id}`);
20+
// Implement guess logic here
21+
};
22+
23+
const handleShowResult = (id: number) => {
24+
console.log(`Showing result for recording ID: ${id}`);
25+
// Implement show result logic here
26+
};
27+
28+
return (
29+
<div className={"w-full mx-4"}>
30+
<h3 className={"hidden"}>Inbox</h3>
31+
<div className={"bg-slate-200 rounded-lg p-4"}>
32+
{recordings.map((recording, index) => (
33+
<>
34+
<article
35+
key={recording.id}
36+
className={
37+
"flex flex-row justify-between gap-2 items-center w-full"
38+
}
39+
>
40+
<span>
41+
<strong>Sender:</strong> {recording.sender}
42+
</span>
43+
<span>
44+
<strong>Receive Time:</strong> {recording.receiveTime}
45+
</span>
46+
<span>
47+
<strong>Guessed:</strong> {String(recording.guessed)}
48+
</span>
49+
<div className={"min-w-[20vw] flex flex-row justify-end"}>
50+
{recording.guessed && (
51+
<button onClick={() => handleGuess(recording.id)}>
52+
Guess
53+
</button>
54+
)}
55+
<button onClick={() => handleShowResult(recording.id)}>
56+
Show Result
57+
</button>
58+
</div>
59+
</article>
60+
{index < recordings.length - 1 && (
61+
<hr className={"border-1 border-slate-700"} />
62+
)}
63+
</>
64+
))}
65+
</div>
66+
</div>
67+
);
68+
}

frontend/islands/ProfileEdit.tsx

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// src/components/EditProfileForm.tsx
2+
import { FunctionalComponent } from "preact";
3+
import { useState } from "preact/hooks";
4+
5+
const ProfileEdit: FunctionalComponent = () => {
6+
const [nickname, setNickname] = useState("");
7+
const [visibility, setVisibility] = useState("public");
8+
9+
const handleSubmit = (event: Event) => {
10+
event.preventDefault();
11+
console.log("Nickname:", nickname);
12+
console.log("Visibility:", visibility);
13+
// Handle form submission logic here
14+
};
15+
16+
return (
17+
<div className="flex items-center justify-center">
18+
<form
19+
onSubmit={handleSubmit}
20+
className="bg-slate-200 p-4 rounded-lg w-full"
21+
>
22+
<div className="mb-4">
23+
<label htmlFor="nickname">Nickname:</label>
24+
<input
25+
type="text"
26+
id="nickname"
27+
name="nickname"
28+
value={nickname}
29+
onChange={(e) => setNickname((e.target as HTMLInputElement).value)}
30+
required
31+
/>
32+
</div>
33+
<div className="mb-4">
34+
<label
35+
htmlFor="visibility">
36+
Visibility:
37+
</label>
38+
<select
39+
id="visibility"
40+
name="visibility"
41+
value={visibility}
42+
onChange={(e) =>
43+
setVisibility((e.target as HTMLSelectElement).value)
44+
}
45+
required
46+
>
47+
<option value="public">Public</option>
48+
<option value="private">Private</option>
49+
<option value="friends">Friends Only</option>
50+
</select>
51+
</div>
52+
<div className={"w-full"}>
53+
<div className={"mx-auto"}>
54+
<button className={"bg-red-400"} type="submit">Save Changes</button>
55+
</div>
56+
</div>
57+
</form>
58+
</div>
59+
);
60+
};
61+
62+
export default ProfileEdit;

frontend/routes/my/index.tsx

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
import { h } from "preact";
1+
import { JSX } from "preact";
22
import Profile from "../../components/profile/profile-desc.tsx"
33

44

55
import { PageProps } from "$fresh/server.ts";
6+
import SectionProfile from "../../components/profile/SectionProfile.tsx";
7+
import SectionInbox from "../../components/profile/SectionInbox.tsx";
8+
import ChevronBg from "../../components/chevronBg.tsx";
9+
import TitleDivider from "../../components/common/TitleDivider.tsx";
610

711
export default function ProfilePage(props: PageProps) {
812
return (
9-
<div>
10-
<div className={" mt-[200px]"}>
11-
<div className={"my-2"}>
12-
<Profile avatarUrl="" name="" bio=""/>
13-
</div>
14-
</div>
15-
</div>
13+
<>
14+
<ChevronBg />
15+
<TitleDivider title="My Profile" />
16+
<SectionProfile />
17+
<TitleDivider title="Inbox" />
18+
<SectionInbox />
19+
<section className={"mb-[200px]"}></section>
20+
</>
1621
);
17-
}
22+
}

0 commit comments

Comments
 (0)