-
Notifications
You must be signed in to change notification settings - Fork 283
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
Js2 #289
base: main
Are you sure you want to change the base?
Js2 #289
Changes from all commits
85417c1
cc9ec0c
e73e5c4
fe3759f
6f5f94a
34a0263
7ebea2c
d0182b8
bb9e828
21bff20
f7eb7c3
2ac0c88
ad9fc71
2ef8bbc
a9481c6
eb9def8
b7fec36
c152c9d
dd1dacc
7bc2668
e4f808b
e9720d2
804c505
3376605
ecbafc7
072a695
9f925e5
cad1710
5b0f2bb
c9b292f
0e66b58
1762614
d122829
a7e88b5
ecfde14
154d9b5
e81e41b
a6792cd
badfad5
01756f6
1b3069a
8971254
69105a7
5aa8f5a
2b162db
33693b7
1707e4f
8df0084
3e4ee9c
a2df904
bce0a37
fe46c92
33cbbab
8d1db5c
5dc4890
d1dbadd
117f582
9f389f0
77faf86
fcd3485
972f211
c34302f
e64ba35
1de3247
57e084b
a29ee5f
9ad4447
52ef317
3c6da6e
ab53cb9
b0d3a8e
ff7387e
8309d39
41d7765
2ef64ac
b255797
4aa6fe6
78d2289
4539ecd
c63a4d4
aef60f8
0c06482
204a782
40bf06a
26e343f
db68456
e458555
42643b3
d03192a
2b0e5fd
8fe756b
eef5e40
4819fd3
ba409a8
a4db607
9972362
e87a74a
6a4326d
5a61ea2
a3d9561
4480e90
3d7a09f
d28d795
22be1b3
62376d4
927b332
59238b3
7d6e7a6
6a02d9e
6e9dd63
3ba6060
e6e0080
f085ef1
b9559f6
aaf3f32
a0ba631
f3e4c25
263e1bd
c64bbd8
cdde4ca
cc7e664
0730cfa
0f8f2e2
f14a339
b14e87c
a4b01c9
2928a02
566b893
f224101
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
node_modules/ | ||
.DS_Store | ||
dist/ | ||
dist/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,115 @@ | ||
# css-frameworks-ca | ||
Replace this text with a description of your social media project. | ||
## js2 social media application | ||
link to trello: https://trello.com/invite/b/HgMSDygC/ATTI59165adf424964b1c8ef6ef67039647001A570D6/javascrip2 | ||
|
||
this is my "social media application" you can register a user (with a valid @noroff(stud.noroff.no). the registerd ouser can login, make posts, edit posts and delete posts. and view others posts. | ||
navigation is clear on the homepage(login) wher there is a button for registration and after registration, there is a button for login, when u have gotten the confiramtion that your logged inn, use the nav bar to get to feed or profile. | ||
|
||
|
||
--- | ||
### made with: | ||
<img src="https://raw.githubusercontent.com/tandpfun/skill-icons/main/icons/HTML.svg" width="50" height="50"> | ||
<img src="https://raw.githubusercontent.com/tandpfun/skill-icons/main/icons/CSS.svg" width="50" height="50"> | ||
<img src="https://raw.githubusercontent.com/tandpfun/skill-icons/main/icons/JavaScript.svg" width="50" height="50"> | ||
<img src="https://raw.githubusercontent.com/tandpfun/skill-icons/main/icons/VSCode-Dark.svg" width="50" height="50"> <img | ||
--- | ||
|
||
Description-- | ||
|
||
## Brief | ||
You have been tasked with producing a new JavaScript front-end client for an existing social media platform. The client application must be attractive and responsive, but you have an otherwise blank slate in terms of theme design language. | ||
|
||
Using the provided API and API documentation, create a functioning user interface that allows for viewing, posting, editing and deleting social media content. | ||
|
||
Social API routes require authorisation via JWT (JSON Web Tokens). You will need to register an account and login to access your token. | ||
|
||
To complete the required features, you will also need to make use of GET, POST, PUT, and DELETE HTTP methods. | ||
|
||
Using localStorage is highly recommended, especially for storing JWT tokens. | ||
|
||
A finished project fulfils the requirements below with an easy to use and error-free user interface. | ||
|
||
Required features | ||
The following user stories are required for a passing submission: | ||
|
||
User with @noroff.no or @stud.noroff.no email can register profile | ||
Registered user can login | ||
User can view a post content feed | ||
User can filter the post content feed | ||
User can search the post content feed | ||
User can view a post content item by ID | ||
User can create a post content item | ||
User can update a post content item | ||
User can delete a post content item | ||
Additional features | ||
The following user stories are optional: | ||
|
||
User can create a comment on a post | ||
User can edit profile media | ||
User can follow/unfollow a profile | ||
User can react to a post content item | ||
|
||
## register | ||
here u can register a profile with a @noroff.no or @stud.noroff.no email, when registrering, you will get a confimation if the registration is successfull, and you will get a error message if the registration was unsucessfull. | ||
|
||
## login | ||
after registring a user, you can take the same email and password and login. | ||
|
||
## feed | ||
in the feed page, when you have logged inn, you can create a post (with a title, body,tags(optionale) and media(optionale) further down the page, u can update(edit) a post that you have created,just click on the edit button on the post u want to edit (to get the post id) .you can also delete a post, if you are unhappy, or if u dont want it out there, its simple, just click on the delete button on the post u want to delete (to get the post id so the post can be deleted) | ||
we have a search fuction, if u wanna see 100 posts of "test" just search test or example" | ||
after that we have a sorting option, where the default is newest, but if you set it to the oldest, the oldests posts (out of the 100 fetched) is being displayed first. | ||
last we have the feed, here you can see the time the posts, the time the have beed posted. | ||
|
||
## profile | ||
|
||
here you can see your profile | ||
i did not get time to make the profile page alot of the things was optionale, so hopefully you can atleast edit your bio, and mabye press the follow button. | ||
|
||
#### Getting Started | ||
|
||
Installing | ||
|
||
Clone the repo: | ||
|
||
git clone git@github.com: https://github.com/Voidwaker/css-frameworks-ca/tree/js2-try2 | ||
|
||
Install the dependencies: N/A | ||
|
||
npm install | ||
|
||
Running | ||
|
||
To run the app, run the following commands: | ||
|
||
npm run dev | ||
|
||
|
||
|
||
|
||
|
||
--- | ||
|
||
Contributing | ||
|
||
|
||
As this is my js2 assignment, i dont want contributions, but feedback to how i can imporve the site is always velcome. Thank you! | ||
|
||
Any suggestions will be happily taken into account- feel free to message me! | ||
--- | ||
|
||
Contact: | ||
|
||
|
||
Email me: | ||
Sigurdvaaler@hotmail.com | ||
|
||
<img src="https://raw.githubusercontent.com/tandpfun/skill-icons/main/icons/Gmail-Dark.svg" width="50" height="50"> <img src="https://raw.githubusercontent.com/tandpfun/skill-icons/main/icons/Discord.svg" width="50" height="50"> | ||
|
||
|
||
Find me on Discord: | ||
(Sigurd Vaaler | ||
Voidwaker1) | ||
|
||
--- | ||
|
||
Acknowledgments: |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Feed</title> | ||
<link rel="stylesheet" href="/dist/css/index.css"> | ||
<script defer src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script> | ||
<script type="module" src="/js/index.mjs" defer></script> | ||
</head> | ||
<body class="bg-dark"> | ||
<header> | ||
<nav class="navbar navbar-expand-lg navbar-light bg-light"> | ||
<div class="container-fluid"> | ||
<a class="navbar-brand" href="/">Home</a> | ||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> | ||
<span class="navbar-toggler-icon"></span> | ||
</button> | ||
<div class="collapse navbar-collapse" id="navbarNav"> | ||
<ul class="navbar-nav"> | ||
<li class="nav-item"> | ||
<a class="nav-link" href="/profile">Profile</a> | ||
</li> | ||
<li class="nav-item"> | ||
<a class="nav-link active" href="/feed/index.html">Feed</a> | ||
</li> | ||
</ul> | ||
</div> | ||
</div> | ||
</nav> | ||
</header> | ||
<main class="container mt-4"> | ||
<div class="card border-dark mb-3 mx-auto"> | ||
<div class="card-body"> | ||
<h5 class="card-title mb-3 text-green text-center">Create New Post</h5> | ||
<form id="createPost"> | ||
<div class="form-group mb-3 text-green"> | ||
<label for="postTitle">Title</label> | ||
<input class="form-control" type="text" id="postTitle" name="title" required> | ||
</div> | ||
<div class="form-group mb-3 text-green"> | ||
<label for="postBody">Body</label> | ||
<textarea class="form-control" id="postBody" name="body" required></textarea> | ||
</div> | ||
<div class="form-group mb-3 text-green"> | ||
<label for="postTags">Tags (comma separated)</label> | ||
<input class="form-control" type="text" id="postTags" name="tags"> | ||
</div> | ||
<div class="form-group mb-3 text-green"> | ||
<label for="postMedia">Media</label> | ||
<input class="form-control" type="url" id="postMedia" name="media"> | ||
</div> | ||
<div class="d-flex justify-content-center"> | ||
<button class="btn btn-success" type="submit">Create Post</button> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
|
||
<div class="card border-dark mb-3 mx-auto"> | ||
<h1 class="fst-italic fw-bold text-center">Edit Posts</h1> | ||
<div class="card-body"> | ||
<form id="editPost"> | ||
<div class="form-group mb-3 text-green"> | ||
<label for="editPostTitle">Title</label> | ||
<input class="form-control" type="text" id="editPostTitle" name="title" required> | ||
</div> | ||
<div class="form-group mb-3 text-green"> | ||
<label for="editPostBody">Body</label> | ||
<textarea class="form-control" id="editPostBody" name="body" required></textarea> | ||
</div> | ||
<div class="form-group mb-3 text-green"> | ||
<label for="editPostTags">Tags</label> | ||
<input class="form-control" type="text" id="editPostTags" name="tags"> | ||
</div> | ||
<div class="form-group mb-3 text-green"> | ||
<label for="editPostMedia">Media</label> | ||
<input class="form-control" type="url" id="editPostMedia" name="media"> | ||
</div> | ||
<div class="d-flex justify-content-center"> | ||
<button class="btn btn-success" type="submit">Update Post</button> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
|
||
<div class="d-flex justify-content-center mb-3"> | ||
<div class="col-md-6 col-lg-4"> | ||
<select id="filterPosts" class="form-control text-green"> | ||
<option value="newest">Newest</option> | ||
<option value="oldest">Oldest</option> | ||
<option value="popular">Most Popular</option> | ||
</select> | ||
</div> | ||
</div> | ||
|
||
<div class="d-flex justify-content-center mb-3"> | ||
<div class="col-md-8"> | ||
<input id="searchPosts" type="text" class="form-control text-green" placeholder="Search for posts..."> | ||
</div> | ||
</div> | ||
|
||
<h1 class="fst-italic fw-bold text-center">Posts</h1> | ||
<div id="posts" class="mt-4"></div> | ||
</main> | ||
</body> | ||
</html> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Login/Registrer</title> | ||
<link rel="stylesheet" href="dist/css/index.css"> | ||
<script defer src="node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script> | ||
<script type="module" src="./js/index.mjs" defer></script> | ||
|
||
</head> | ||
<body class="bg-dark"> | ||
<header class="container-fluid"> | ||
<nav class="navbar navbar-expand-lg navbar-light bg-light"> | ||
<div class="container-fluid"> | ||
<a class="navbar-brand" href="/">Home</a> | ||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> | ||
<span class="navbar-toggler-icon"></span> | ||
</button> | ||
<div class="collapse navbar-collapse" id="navbarNav"> | ||
<ul class="navbar-nav"> | ||
<li class="nav-item"> | ||
<a class="nav-link" href="/profile">Profil</a> | ||
</li> | ||
<li class="nav-item"> | ||
<a class="nav-link" href="/feed/index.html">Feed</a> | ||
</li> | ||
<li class="nav-item"> | ||
<a class="nav-link" href="/index.html">Logout</a> | ||
</li> | ||
</ul> | ||
</div> | ||
</div> | ||
</nav> | ||
</header> | ||
<div class="container-sm col-6 mt-5"> | ||
<h2 class="text-center">Logg Inn</h2> | ||
<form id="loginForm"> | ||
<div class="mb-3"> | ||
<label for="loginEmail" class="form-label text-blue">E-post</label> | ||
<input type="email" class="form-control text-green" id="loginEmail" name="email" placeholder="Email@example.com" required> | ||
</div> | ||
<div class="mb-3"> | ||
<label for="loginPassword" class="form-label text-blue">Passord</label> | ||
<input type="password" class="form-control text-green" id="loginPassword" name="password" placeholder="Password" required minlength="8"> | ||
</div> | ||
<div class="d-flex justify-content-center"> | ||
<button type="submit" class="btn btn-custom">Logg Inn</button> | ||
</div> | ||
</form> | ||
<div id="errorDisplay" style="color: red;"></div> | ||
<div class="d-flex justify-content-center mt-3"> | ||
<a href="register.html" class="btn btn-custom">Register</a> | ||
</div> | ||
</div> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { load } from "../../storage/index.mjs"; | ||
|
||
export function headers() { | ||
const token = load("token"); | ||
|
||
return { | ||
"Content-Type": "application/json", | ||
"Authorization": `Bearer ${token}` | ||
}; | ||
} | ||
|
||
export async function authFetch(url, options = {}){ | ||
const requestOptions = { | ||
...options, | ||
headers: { | ||
...headers(), | ||
...options.headers | ||
} | ||
}; | ||
|
||
try { | ||
const response = await fetch(url, requestOptions); | ||
return response; | ||
} catch (error) { | ||
console.error('Feil under fetch:', error); | ||
throw error; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Understand the differences, they have different purposes. Here you're basically catching an error and throwing it again. Suggestion: remove the throw from the catch block and use the try/catch block in a UI/UX code block e.g event listener. |
||
} | ||
} | ||
|
||
|
||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { API_SOCIAL_URL } from "../constants.mjs"; | ||
import * as storage from "../../storage/index.mjs"; | ||
|
||
const action = "/auth/login"; | ||
const method = "POST"; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed opportunity for JSDocs here. |
||
export async function login(profile){ | ||
const loginURL = API_SOCIAL_URL + action; | ||
const body = JSON.stringify(profile); | ||
|
||
const Response = await fetch(loginURL, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
method, | ||
body | ||
}); | ||
|
||
const {accessToken, ...user} = await Response.json(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Object destructuring - good job! |
||
storage.save('token', accessToken); | ||
storage.save('profile', user); | ||
|
||
alert('Login successful'); | ||
} | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { API_SOCIAL_URL } from "../constants.mjs"; | ||
|
||
const action = "/auth/register"; | ||
const method = "POST"; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed opportunity for JSDocs here. |
||
export async function register(profile){ | ||
const registerURL = API_SOCIAL_URL + action; | ||
const body = JSON.stringify(profile); | ||
|
||
const Response = await fetch(registerURL, { | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
method, | ||
body | ||
}); | ||
|
||
const response = await Response.json(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
alert('Registration successful'); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export const API_HOST_URL = 'https://api.noroff.dev/api/v1'; | ||
export const API_BASE = '/api/v1'; | ||
export const API_SOCIAL_BASE = '/social'; | ||
export const API_SOCIAL_URL = `${API_HOST_URL}${API_SOCIAL_BASE}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A conditional statement is missing here to check if the
response
is OK or not.