这是indexloc提供的服务,不要输入任何密码
Skip to content
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
4 changes: 4 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "next/core-web-vitals",
"rules": { "react/no-unescaped-entities": 0 }
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# dependencies
/node_modules
package-lock.json
/.pnp
.pnp.js

Expand Down
4,282 changes: 3,539 additions & 743 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@
"framer-motion": "^10.16.4",
"html-react-parser": "^4.2.2",
"html2pdf.js": "^0.10.1",
"next": "13.4.19",
"next": "^14.1.0",
"postcss": "8.4.28",
"react": "18.2.0",
"react": "^18.2.0",
"react-countup": "^6.4.2",
"react-dom": "18.2.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"react-icons": "^4.10.1",
"react-paystack": "^5.0.0",
"tailwindcss": "3.3.3",
"use-local-storage": "^3.0.0",
"uuid": "^9.0.1"
},
"devDependencies": {
"eslint": "8.56.0",
"eslint-config-next": "14.1.0"
}
}
6 changes: 5 additions & 1 deletion src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@
}

.cat {
@apply px-10 py-3 bg-gray-200 text-black rounded-md sm:py-2 sm:px-6 hover:bg-primary1 hover:text-white;
@apply px-5 py-1 bg-gray-200 text-black rounded-md sm:py-2 sm:px-6 hover:bg-primary1 hover:text-white;
}

.presscat {
@apply bg-primary1;
}

input,
Expand Down
11 changes: 11 additions & 0 deletions src/app/resources/[id]/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client"
import Resources from '@/components/Resources'
import React from 'react'

const page = ({params}) => {
return (
<Resources book={params.id}/>
)
}

export default page
File renamed without changes.
2 changes: 1 addition & 1 deletion src/atomic_components/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const Footer = () => {
<div className="flex gap-10 text-gray-100">
{nav.map((item, i) => {
return (
<a href={item.link} className="text-[0.8em]">
<a key={i} href={item.link} className="text-[0.8em]">
{item.title}
</a>
);
Expand Down
205 changes: 205 additions & 0 deletions src/atomic_components/ResourceContent.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
// "use client";

import { error } from "@/utils/toastify";
import axios from "axios";
import Loader from '../components/Loader';
import NoContent from '@/atomic_components/NoContent';
import React, { useEffect, useState } from "react";
import { FaDownload } from "react-icons/fa";

let axiosHandler = axios.create({
baseURL: "http://127.0.0.1:8000/library/"
})

function formatSize(size) {
return (size / (1024 * 1024)).toFixed(1) + ' MB';
}

const ResourceContent = ({book}) => {
const [loading, setLoading] = useState(true);
const [bookObj, setBookObj] = useState(null);
const [courses, setCourses] = useState(null);
const [level, setLevel] = useState(null);
const [dept, setDept] = useState(null);
const [course, setCourse] = useState(null);

const levels = {
"100": 100,
"200": 200,
"300": 300,
"400": 400,
"500": 500,
"TXT": 0,
}

const depts = ["ABE", "CVE", "ELE", "GEN", "MCE", "MTE"]

useEffect(() => {
axiosHandler.get('codes/')
.then((response) => {
setCourses(response.data.map(course => course.code));
})
axiosHandler.get(`books/${book}/`)
.then((books) => {
setBookObj(books.data);
})
.then(() => {
setLoading(false);
})
}, []);

const handleBack = () => {
window.location.href = `/resources`;
}

const handleLevel = (e) => {
setLevel(e.target.value);
}

const handleDept = (e) => {
setDept(e.target.value);
}

const handleCourse = (e) => {
setCourse(e.target.value);
}

function update(e) {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const formJson = Object.fromEntries(formData.entries());
let data = {
title: formJson.title,
description: formJson.desc,
level,
tag: dept,
code: course,
}
axiosHandler.put(`books/${book}/`, data);
}

return (
<div>
{
loading ? (
<div className="text-center">
<Loader />
</div>
) : (
<div>
<div className="flex justify-between">
<button className="bg-red-500 text-white px-4 py-2 rounded-xl" onClick={handleBack}>Back</button>
<button
className="bg-orange-500 text-white px-4 py-2 rounded-xl"
onClick={() => { axiosHandler.put(`books/${book}/`, {'downloads': bookObj.downloads + 1}) }}
>
<a
href="https://docs.google.com/forms/d/e/1FAIpQLScy0bLFM7anOP16saKccBjWB6FSggMaztohBiwAfmszCn5Y8g/viewform?usp=sf_link"
target="_blank"
>Report</a>
</button>
</div>
<div>
<div>
<h2 className="px-2 py-2 flex flex-col break-words text-center text-2xl font-bold">{bookObj.title}</h2>
</div>
<span className="flex flex-row-reverse">, {bookObj.downloads} Downloads<span className="italic flex-row-reverse">By {bookObj.uploader.username}</span></span>
<form onSubmit={update} className="flex flex-col gap-3">
<div>
<label htmlFor="title">Title:</label>
<input
className="focus:border-slate-300 shadow-sm shadow-slate-500"
type="text" name="title" id="title" defaultValue={bookObj.title} />
</div>
<div>
<label htmlFor="title">Description:</label>
<textarea
className="focus:border-slate-300 shadow-sm shadow-slate-500"
name="desc" id="desc" defaultValue={bookObj.description}
rows="4" cols="50"
></textarea>
</div>
<div className="flex flex-row justify-between">
<label>
Level:
<select
className="focus:border-slate-300 shadow-sm shadow-slate-500"
id="selectedLevel"
onChange={handleLevel}
>
{Object.values(levels).map((level) => {
return (
<option
key={`${level}`}
value={`${level}`}
selected={level == bookObj.level}
>{level == 0 ? "TXT" : `${level}`}</option>
)})}
</select>
</label>
<label>
Dept:
<select
id="selectedDept"
className="focus:border-slate-300 shadow-sm shadow-slate-500"
onChange={handleDept}
>
{depts.map((dept, index) => {
return (
<option
key={index}
value={`${dept}`}
selected={dept === bookObj.tag}
>{dept}</option>
)
})}
</select>
</label>
<label>
Course:
<select
id="slectedCourse"
className="focus:border-slate-300 shadow-sm shadow-slate-500"
onChange={handleCourse}
>
{courses.map((course) => {
return (
<option
key={course}
value={course}
selected={course === bookObj.code}
>{course}</option>
)
})}
{bookObj.code ?
<></> :
<><option value={"GEN"} selected>{"Text Book"}</option></>
}
</select>
</label>
{/* Add other labels that may be readonly */}
</div>
<div className="flex flex-row-reverse">
<button
className="bg-primary1 hover:bg-green-600 text-white text-center px-4 py-2 rounded-md"
type="submit"
name="save"
> Save </button>
</div>
</form>
<div className="flex flex-row-reverse mt-2">
<button
className="bg-primary1 hover:bg-green-600 text-white px-4 py-2 rounded-md"
>
<a href={`${bookObj.download}`}>Download {formatSize(bookObj.size)}</a>
</button>
</div>
</div>
</div>
)}
</div>
);
}

export default ResourceContent;
Loading