Skip to content
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

Add Comment Section #26

Merged
merged 4 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/modules/api/Comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import axios from 'axios';

export default class Comments {
constructor() {
this.involvementApi = process.env.INVOLVEMENT_API_LINK;
this.involvementApiId = process.env.INVOLVEMENT_ID;
this.commentsEndPoint = `/apps/${this.involvementApiId}/comments`;
this.commentsAllEndPoint = `/apps/${this.involvementApiId}/comments?item_id=`;
}
/**
* call to Involvement APi for getting comments
* @param id
* @returns api data
*/

// eslint-disable-next-line consistent-return
getComments = async (id) => {
try {
// eslint-disable-next-line consistent-return
return await axios.get(`${this.involvementApi}${this.commentsAllEndPoint}${id}`).then((res) => {
if (res.status === 200) {
return res;
}
});
} catch (error) {
if (error.response) {
return false;
}
}
}

/**
* call to Involvement APi for adding new
* @param itemId, username, comment
* @returns api data
*/
addComment = async (itemId, username, comment) => {
try {
// eslint-disable-next-line consistent-return
return await axios.post(`${this.involvementApi}${this.commentsEndPoint}`, {
item_id: itemId,
username,
comment,
}).then((res) => {
if (res.status === 201) {
return true;
}
throw new Error('Fail');
});
} catch (error) {
throw new Error('Fail');
}
}
}
24 changes: 19 additions & 5 deletions src/modules/api/ShowApi.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import axios from 'axios';
// eslint-disable-next-line import/no-cycle, import/no-unresolved
import { navigator } from '../router/router.js';
// eslint-disable-next-line import/no-cycle
import Comments from './Comment.js';

export default class ShowApi {
export default class ShowApi extends Comments {
constructor() {
super();
this.movieApi = process.env.MOVIEDB_API_LINK;
this.movieApiSecret = process.env.MOVIEDB_API_SECRET;
this.involvementApi = process.env.INVOLVEMENT_API_LINK;
this.involvementApiId = process.env.INVOLVEMENT_ID;
this.apiSecretCall = `?api_key=${this.movieApiSecret}&language=en-US`;
this.noMovieMsg = 'Request failed with status code 404';
}

/**
* call to movie db for getting people
* @param {id} id
* @returns api data
*/
people = async (id) => {
try {
return await axios.get(`${this.movieApi}/${id}/credits${this.apiSecretCall}`).then((res) => (res.data));
Expand All @@ -25,6 +31,11 @@ export default class ShowApi {
}
}

/**
* call to movie db for getting recommended movie
* @param {id} id
* @returns api data
*/
recommendations = async (id) => {
try {
return await axios.get(`${this.movieApi}/${id}/recommendations${this.apiSecretCall}`).then((res) => (res.data));
Expand All @@ -33,6 +44,11 @@ export default class ShowApi {
}
}

/**
* call to movie db for getting the movie by id
* @param {id} id
* @returns api data
*/
show = async (id) => {
try {
// eslint-disable-next-line consistent-return
Expand All @@ -43,8 +59,6 @@ export default class ShowApi {
});
} catch (error) {
if (error.message === this.noMovieMsg) {
// window.history.pushState({ path: '404' }, '404', 'error');
// navigator('/404');
throw new Error('No such page');
}
throw new Error('No such page');
Expand Down
3 changes: 3 additions & 0 deletions src/modules/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ export default class Main {
links();
});
};

js = async () => {
}
}
11 changes: 3 additions & 8 deletions src/modules/router/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ const scrollToTop = () => {
set to el.innerHtml
*/
const newPage = async (Page, el, obj = {}) => {
// intiial image should be null
// initial image should be null
const images = document.querySelectorAll('.image');
images.forEach((image) => { image.innerHTML = ''; });
imgHelper();
const page = new Page();
el.innerHTML = await page.html(obj);
await page.js();
links();
scrollToTop();
};
Expand All @@ -54,8 +55,6 @@ const noPage = (el) => {

// for main navigation
const navigator = (path) => {
// get main
const main = document.querySelector('.main');
let route = path;
let hash;
if (route.includes('#')) {
Expand All @@ -64,19 +63,15 @@ const navigator = (path) => {
}
const routeInfo = routerInstance.routes.filter((rou) => (rou.path === route || `${rou.path}/` === route))[0];
if (!routeInfo || path === '404') {
noPage(main);
// eslint-disable-next-line no-use-before-define
router();
} else if (routeInfo.params && hash) {
newPage(routeInfo.page, main, { hash: Number(window.location.hash) });
// eslint-disable-next-line no-use-before-define
router();
} else if (!routeInfo.params) {
newPage(routeInfo.page, main, {});
// eslint-disable-next-line no-use-before-define
router();
} else {
noPage(main);
// eslint-disable-next-line no-use-before-define
router();
}
Expand All @@ -85,7 +80,7 @@ const navigator = (path) => {
/**
* navigate according to button
*/
const navigate = (event) => {
const navigate = async (event) => {
event.preventDefault();
let route = event.target.attributes[0].value;
let hash;
Expand Down
118 changes: 115 additions & 3 deletions src/modules/show.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ export default class Show extends ShowApi {
super();
this.color = ['blue', 'green', 'red', 'aqua', 'lightblue'];
this.photo = 'https://image.tmdb.org/t/p/original';
this.itemNotFound = "item_id' not found.";
}

/**
* change to smaller string for the given length text
* @param num
* @returns string
*/
toText = (num) => {
let string = num;
for (let i = 3; i < num.toString().length; i += 4) {
Expand All @@ -16,6 +22,11 @@ export default class Show extends ShowApi {
return string;
}

/**
* get in string format for innerHtml adding: get show more show less button
* @param string
* @returns string
*/
showMore = (str) => {
let string = str;
if (str.length > 100) {
Expand All @@ -31,13 +42,23 @@ export default class Show extends ShowApi {
return string;
}

/**
* get in string format for innerHtml adding: adding genre
* @param Array
* @returns string
*/
toGenre = (genres) => {
if (genres.length > 0) {
return Array.from(genres, (e) => `<span class="genre" style="background-color:${this.color[Math.floor(Math.random() * this.color.length)]}">${e.name}</span>`).join('');
}
return 'N/A';
}

/**
* get in string format for innerHtml adding: adding people
* @param Array
* @returns string
*/
toPeople = (p) => {
let string = '';
for (let i = 0; i < 5 && i < p.length; i += 1) {
Expand All @@ -46,38 +67,117 @@ export default class Show extends ShowApi {
return string;
}

/**
* get in string format for innerHtml adding: adding recommendations cards
* @param Array
* @returns string
*/
toRecommendations = (data) => {
let string = '';
for (let i = 0; i < 5 && i < data.length; i += 1) {
string += `<div class="cast-card"><div>${this.checkNull(data[i].poster_path, `<img href="/movie#${data[i].id}" onclick="navigate(e)" src="${this.photo}${data[i].poster_path}" class="cast-photo spaLink" alt="photo">`)}</div><span>${data[i].title}</span></div>`;
string += `<div class="cast-card"><div>${this.checkNull(data[i].poster_path, `<img href="/movie#${data[i].id}" src="${this.photo}${data[i].poster_path}" class="cast-photo spaLink" alt="photo">`)}</div><span>${(data[i].title.length > 20) ? `${data[i].title.slice(0, 20)}...` : data[i].title}</span></div>`;
}
return string;
}

/**
* check null or not if null return 'N/A' otherwise text
* @param (data: noyNullStr, text: Str)
* @returns string
*/
checkNull = (data, text) => {
if (!data) {
return 'N/A';
}
return text;
}

/**
* change to the data objects
* @param str
* @returns string
*/
toDate = (str) => {
const date = new Date(str);
return `${date.getDate()}/${date.getMonth()}/${date.getFullYear()}`;
}

/**
* get in string format for innerHtml adding: adding comments
* @param (obj: comments)
* @returns string
*/
toComments = (data) => {
let string = '';
data.forEach((comment) => {
string += `<div class="comment">
<span>${this.toDate(comment.creation_date)}</span>
<span>${comment.username}</span>
<span>${comment.comment}</span>
</div>`;
});
return string;
}

/**
* get the comments length that is in dom
* @param
* @returns comments length
*/
commentsLength = () => {
const commentsLength = document.querySelector('#comments-length');
const comments = document.querySelectorAll('.comment');
commentsLength.innerHTML = comments.length;
return comments.length;
}
/**
* to run the javascript code after the html from the class is finished
* @param ()
*/

js = () => {
const form = document.querySelector('.form');

form.addEventListener('submit', async (e) => {
e.preventDefault();
const commentsEl = document.querySelector('.comments');
this.addComment(e.target.id, e.target[0].value, e.target[1].value).then(async (res) => {
if (res === true) {
const comments = await this.getComments(e.target.id);
commentsEl.innerHTML = this.toComments(comments.data);
this.commentsLength();
e.target.reset();
}
});
});
this.commentsLength();
}

/**
* for main.innerHtml data
* @param ()
* @return (main.innerHtml: string)
*/
html = async ({ hash }) => {
const res = await this.show(Number(hash)).then((data) => data);
const {
id, genres, title, overview, budget,
} = res;
const posterPath = res.poster_path;
const rating = res.vote_average;
const releaseDate = res.release_date;
const releaseDate = this.toDate(res.release_date);
const language = res.original_language;
const people = await this.people(id).then((data) => data);
const recommendations = await this.recommendations(id).then((data) => data);
const comments = await this.getComments(id);
return (`
<section class="main-section">
<div id="show">
<div class="popup-header">
<h2>${title}</h2>
<i class="fa-solid fa-xmark"></i>

<i href="/" class="spaLink fa-solid fa-xmark"></i>

</div>
<div class="details">
<div class="movie-img">
Expand Down Expand Up @@ -105,6 +205,18 @@ export default class Show extends ShowApi {
<div class="recommendations">
${this.toRecommendations(recommendations.results)}
</div>

<h3 class="comments-header">Comments(<span id="comments-length"></span>)</h3>
<div class="comments">
${(comments === false) ? 'No comments yet' : this.toComments(comments.data)}
</div>

<h3 class="comment-header">Add a comment</h3>
<form id="${id}" class="form comment-form">
<input class="input-box input-name" placeholder="Your Name" required>
<textarea class="input-box" rows="10" placeholder="Your Insight" required></textarea>
<button class="input-btn" type='submit'>Submit</button>
</form>
</div>

</section>`
Expand Down
Loading