Skip to content

Commit 6d7d5e0

Browse files
Enhance UI and functionality: added quick links sidebar, improved avatar management, and refined login form validation
1 parent e68138a commit 6d7d5e0

File tree

7 files changed

+292
-34
lines changed

7 files changed

+292
-34
lines changed

README.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Social Network Web Application
2+
3+
## Project Overview
4+
5+
This is a simple social network web application prototype that enables user registration, login, posting content (text and images), commenting, liking posts, and managing user avatars. It is a client-side application that uses localStorage for data persistence.
6+
7+
## Main Features
8+
9+
- User Registration and Login with form validation
10+
- User session maintained via localStorage
11+
- Create posts with text and optional image upload
12+
- View posts with author info, timestamps, likes, and comments
13+
- Edit and delete posts and comments owned by the current user
14+
- Upload and remove user profile avatars
15+
- Quick Links sidebar for navigation
16+
- Responsive layout with sidebar toggling on small screens
17+
- Notifications and confirmation dialogs using SweetAlert2
18+
- Simple time ago formatting for post timestamps
19+
20+
## Project Structure
21+
22+
### HTML
23+
24+
- `index.html`: Main landing page showing user’s feed and post creation UI.
25+
- `loginform/login.html`: Login form page (scripts included here for login form handling).
26+
- `sign-inform/signin.html`: Signup form page (scripts included here for registration handling).
27+
28+
### CSS
29+
30+
- All CSS files are under `assets/css/`
31+
- `style.css`: Main stylesheet for the application styling.
32+
- `login.css` and `signup.css`: Styles for login and signup pages respectively.
33+
34+
### JavaScript
35+
36+
- `assets/js/app.js`: Main application logic for home page, including posts, comments, avatars, UI behaviors.
37+
- `assets/js/login.js`: Handles login page form validation and submission.
38+
- `assets/js/signin.js`: Handles signup page form validation and submission.
39+
40+
### Libraries
41+
42+
- Bootstrap for responsive styling and UI components.
43+
- Font Awesome for icons.
44+
- SweetAlert2 for modals and alerts.
45+
46+
## How It Works
47+
48+
- When a user visits the login page, they can enter their credentials to log in or navigate to the signup page.
49+
- On signup, user data is saved to localStorage and the user is auto-logged in.
50+
- Upon successful login, users are redirected to the main page (`index.html`).
51+
- Users can create posts with text and images. Posts are saved in localStorage.
52+
- Users can like, comment, edit, and delete their own posts and comments.
53+
- User profile avatars can be uploaded, previewed, and removed.
54+
- Posts display author info and timestamps formatted as relative time (e.g., "2 hours ago").
55+
- UI includes responsive navigation and sidebar toggling for better usability on small devices.
56+
57+
## How to Run
58+
59+
1. Open `loginform/login.html` in a browser to log in.
60+
2. Open `sign-inform/signin.html` to register a new account.
61+
3. After logging in, `index.html` serves as the main application screen.
62+
4. No backend server is required; this is a fully client-side app using browser localStorage.
63+
64+
## Notes
65+
66+
- All data is stored locally in the browser's localStorage; refreshing or clearing browser data will erase users and posts.
67+
- Image uploads are handled as base64 data URLs stored in localStorage.
68+
- This is a prototype and not meant for production use.
69+
70+
## Future Improvements
71+
72+
- Implement server-side backend and database for persistence.
73+
- Add real authentication and security features.
74+
- Improve UI/UX and accessibility.
75+
- Add friend and notification systems.
76+
77+
---
78+
79+
_Created by AliMazhar (example author), Social Network Demo Project._

assets/css/style.css

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
/* Global Styles */
2+
3+
* {
4+
margin: 0;
5+
padding: 0;
6+
box-sizing: border-box;
7+
}
8+
9+
body {
10+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
11+
background-color: var(--bg-color);
12+
color: var(--text-color);
13+
padding-top: 56px;
14+
}
15+
216
:root {
317
--primary-color: #344F7E;
418
--secondary-color: #273A5C;
@@ -43,18 +57,7 @@
4357
background: linear-gradient(to right, var(--primary-color), var(--secondary-color)) !important;
4458
}
4559

46-
* {
47-
margin: 0;
48-
padding: 0;
49-
box-sizing: border-box;
50-
}
5160

52-
body {
53-
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
54-
background-color: var(--bg-color);
55-
color: var(--text-color);
56-
padding-top: 56px;
57-
}
5861

5962
/* Navigation */
6063
.navbar {
@@ -590,6 +593,27 @@ body {
590593
max-height: 350px;
591594
overflow-y: auto;
592595
padding: 5px 0;
596+
user-select: text;
597+
/* To control color of selected text */
598+
}
599+
600+
.comments-list::selection,
601+
.comments-list *::selection {
602+
background-color: transparent;
603+
/* Prevent blue highlight on selection */
604+
}
605+
606+
.comment-menu {
607+
position: absolute;
608+
right: 0;
609+
top: 3px;
610+
/* Moved further up from 8px */
611+
background: white;
612+
border-radius: 8px;
613+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
614+
min-width: 130px;
615+
z-index: 1000;
616+
overflow: hidden;
593617
}
594618

595619
.comment-item {
@@ -670,7 +694,7 @@ body {
670694
.comment-menu {
671695
position: absolute;
672696
right: 0;
673-
top: 25px;
697+
top: 8px;
674698
background: white;
675699
border-radius: 8px;
676700
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@@ -679,6 +703,16 @@ body {
679703
overflow: hidden;
680704
}
681705

706+
.comment-text:hover {
707+
text-decoration: none;
708+
color: inherit;
709+
outline: none;
710+
}
711+
712+
.comment-text:focus {
713+
outline: none;
714+
}
715+
682716
.comment-menu button {
683717
width: 100%;
684718
padding: 10px 14px;
@@ -734,12 +768,38 @@ body {
734768
.sidebar {
735769
padding: 0 10px;
736770
}
771+
772+
/* Quick Links Sidebar toggle styles for small screens */
773+
#quickLinksSidebar.d-none {
774+
display: none !important;
775+
}
776+
777+
#quickLinksSidebar.d-block {
778+
position: fixed !important;
779+
top: 56px;
780+
/* height of navbar */
781+
left: 0;
782+
height: calc(100vh - 56px);
783+
width: 250px;
784+
background-color: #fff;
785+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
786+
overflow-y: auto;
787+
z-index: 1050;
788+
padding: 1rem;
789+
}
790+
791+
/* Make sure main container has some left margin when sidebar visible */
792+
body:not(.quickLinksOpen) #quickLinksSidebar.d-block+.main-container {
793+
margin-left: 0;
794+
}
737795
}
738796

739797
@media (max-width: 768px) {
740798
.main-container {
741-
padding: 0 5px; /* Reduce horizontal padding to avoid horizontal scroll caused by Bootstrap row negative margins */
742-
overflow-x: hidden; /* Prevent horizontal overflow */
799+
padding: 0 5px;
800+
/* Reduce horizontal padding to avoid horizontal scroll caused by Bootstrap row negative margins */
801+
overflow-x: hidden;
802+
/* Prevent horizontal overflow */
743803
}
744804

745805
.feed-container {

assets/js/app.js

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ function init() {
2424
// Display user info
2525
displayUserInfo();
2626

27+
// Show or hide the remove avatar button
28+
toggleRemoveAvatarBtn();
29+
2730
// Load posts from localStorage
2831
loadPosts();
2932

@@ -33,6 +36,12 @@ function init() {
3336
// Set up avatar upload handler
3437
setupAvatarUpload();
3538

39+
// Setup quick links sidebar toggle button
40+
setupQuickLinksToggle();
41+
42+
// Setup remove avatar button click
43+
setupRemoveAvatarBtn();
44+
3645
// Close menus when clicking outside
3746
document.addEventListener("click", function (e) {
3847
// Close post menus
@@ -48,6 +57,86 @@ function init() {
4857
});
4958
}
5059
});
60+
61+
// Toggle Quick Links sidebar visibility on small screens
62+
function setupQuickLinksToggle() {
63+
const toggleBtn = document.getElementById("quickLinksToggleBtn");
64+
const quickLinksSidebar = document.getElementById("quickLinksSidebar");
65+
if (toggleBtn && quickLinksSidebar) {
66+
toggleBtn.addEventListener("click", () => {
67+
if (quickLinksSidebar.classList.contains("d-none")) {
68+
quickLinksSidebar.classList.remove("d-none");
69+
quickLinksSidebar.classList.add(
70+
"d-block",
71+
"position-fixed",
72+
"bg-white",
73+
"shadow",
74+
"vh-100",
75+
"overflow-auto"
76+
);
77+
quickLinksSidebar.style.top = "56px"; // below navbar
78+
quickLinksSidebar.style.left = "0";
79+
quickLinksSidebar.style.zIndex = "1050";
80+
document.body.style.overflow = "hidden"; // prevent body scroll
81+
} else {
82+
quickLinksSidebar.classList.add("d-none");
83+
quickLinksSidebar.classList.remove(
84+
"d-block",
85+
"position-fixed",
86+
"bg-white",
87+
"shadow",
88+
"vh-100",
89+
"overflow-auto"
90+
);
91+
quickLinksSidebar.style.top = "";
92+
quickLinksSidebar.style.left = "";
93+
quickLinksSidebar.style.zIndex = "";
94+
document.body.style.overflow = ""; // restore scroll
95+
}
96+
});
97+
}
98+
}
99+
100+
// Show or hide remove avatar button
101+
function toggleRemoveAvatarBtn() {
102+
const avatar = localStorage.getItem(`avatar_${currentUser.email}`);
103+
const removeBtn = document.getElementById("removeAvatarBtn");
104+
if (removeBtn) {
105+
removeBtn.style.display = avatar ? "block" : "none";
106+
}
107+
}
108+
109+
// Setup remove avatar button event handler
110+
function setupRemoveAvatarBtn() {
111+
const removeBtn = document.getElementById("removeAvatarBtn");
112+
if (removeBtn) {
113+
removeBtn.addEventListener("click", () => {
114+
Swal.fire({
115+
title: "Remove Avatar?",
116+
text: "Are you sure you want to remove your profile avatar?",
117+
icon: "warning",
118+
showCancelButton: true,
119+
confirmButtonColor: "#d33",
120+
cancelButtonColor: "#344F7E",
121+
confirmButtonText: "Yes, remove it!",
122+
cancelButtonText: "Cancel",
123+
}).then((result) => {
124+
if (result.isConfirmed) {
125+
localStorage.removeItem(`avatar_${currentUser.email}`);
126+
displayAvatar();
127+
toggleRemoveAvatarBtn();
128+
Swal.fire({
129+
icon: "success",
130+
title: "Avatar removed!",
131+
confirmButtonColor: "#344F7E",
132+
timer: 1500,
133+
showConfirmButton: false,
134+
});
135+
}
136+
});
137+
});
138+
}
139+
}
51140
}
52141

53142
// Display user information
@@ -145,11 +234,12 @@ function setupImageUpload() {
145234
}
146235
}
147236

148-
// Load posts from localStorage
237+
// Load posts from localStorage and filter posts by current user
149238
function loadPosts() {
150239
const savedPosts = localStorage.getItem("posts");
151240
if (savedPosts) {
152-
posts = JSON.parse(savedPosts);
241+
const allPosts = JSON.parse(savedPosts);
242+
posts = allPosts.filter((post) => post.author.email === currentUser.email);
153243
} else {
154244
posts = [];
155245
}

0 commit comments

Comments
 (0)