136 lines
5.4 KiB
TypeScript
136 lines
5.4 KiB
TypeScript
import { ArrowDownTrayIcon, ClipboardIcon } from "@heroicons/react/24/outline";
|
|
import axios from "axios";
|
|
import { useEffect, useState } from "react";
|
|
import { useParams } from "react-router-dom";
|
|
import { toast } from "react-toastify";
|
|
import { Tp } from "../type/TpType";
|
|
|
|
function Practical() {
|
|
const { id } = useParams();
|
|
const [tp, setTp] = useState<Tp>();
|
|
|
|
const copyText = (copy: string) => {
|
|
navigator.clipboard.writeText(copy);
|
|
toast.success("Copied!", {
|
|
draggable: true,
|
|
theme: localStorage.getItem("theme") || "dark",
|
|
});
|
|
};
|
|
|
|
useEffect(() => {
|
|
axios.get(`/api/tps/${id}`).then((res) => {
|
|
setTp(res.data);
|
|
});
|
|
}, [id]);
|
|
|
|
return (
|
|
<>
|
|
{tp && (
|
|
<>
|
|
<h1 className="text-3xl font-bold mb-2 ms-10">{tp.name}</h1>
|
|
<div className="px-6">
|
|
<div className="flex flex-col lg:flex-row">
|
|
<div className="lg:w-2/3 p-4">
|
|
<div className="w-full h-[80vh] bg-gray-200 rounded-lg overflow-hidden mb-4">
|
|
<iframe
|
|
src={tp.pdfLink}
|
|
className="w-full h-full"
|
|
title={`${tp.name} PDF`}
|
|
></iframe>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="lg:w-1/3 px-4">
|
|
<div className="bg-base-200 p-6 rounded-lg shadow-md mt-4">
|
|
<h2 className="text-2xl font-semibold text-blue-600 mb-2">
|
|
Information
|
|
</h2>
|
|
<ul className="space-y-4">
|
|
<li>{tp.description}</li>
|
|
<li className="flex justify-between">
|
|
<span>Duration:</span>
|
|
<span className="font-medium">2 hours</span>
|
|
</li>
|
|
<li className="flex justify-between">
|
|
<span>Tools Used:</span>
|
|
<span className="font-medium">Python, SSH, Vim</span>
|
|
</li>
|
|
<li className="flex justify-between">
|
|
<span>Difficulty:</span>
|
|
<span className="font-medium">Beginner</span>
|
|
</li>
|
|
<li className="flex justify-between">
|
|
<span>Date:</span>
|
|
<span className="font-medium">Oct 23, 2024</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div className="bg-base-200 p-6 rounded-lg shadow-md mt-6">
|
|
<h2 className="text-2xl font-semibold text-blue-600 mb-2">
|
|
Resources
|
|
</h2>
|
|
<ul className="space-y-2">
|
|
<li className="flex justify-between align-middle items-center">
|
|
<span>SSH:</span>
|
|
<div
|
|
className="flex gap-2 items-center"
|
|
onClick={() => copyText(tp.ssh)}
|
|
>
|
|
<span className="font-medium">{tp.ssh}</span>
|
|
<div className="h-8 w-8 hover:bg-base-100 align-middle cursor-pointer flex items-center justify-center rounded">
|
|
<ClipboardIcon className="size-6" />
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li className="flex justify-between align-middle items-center">
|
|
<span>Port:</span>
|
|
<div
|
|
className="flex gap-2 items-center"
|
|
onClick={() => copyText(tp.port)}
|
|
>
|
|
<span className="font-medium">{tp.port}</span>
|
|
<div className="h-8 w-8 hover:bg-base-100 align-middle cursor-pointer flex items-center justify-center rounded">
|
|
<ClipboardIcon className="size-6" />
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li className="flex justify-between align-middle items-center">
|
|
<span>Password:</span>
|
|
<div
|
|
className="flex gap-2 items-center"
|
|
onClick={() => copyText(tp.pwd)}
|
|
>
|
|
<span className="font-normal">{tp.pwd}</span>
|
|
<div className="h-8 w-8 hover:bg-base-100 align-middle cursor-pointer flex items-center justify-center rounded">
|
|
<ClipboardIcon className="size-6" />
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<a
|
|
href={tp.pdfLink}
|
|
target="_blank"
|
|
className="card w-full bg-base-200 shadow-md hover:shadow-lg transition-shadow rounded-lg mt-6"
|
|
>
|
|
<div className="card-body flex-row justify-between items-center">
|
|
<div>
|
|
<div className="card-title text-lg font-bold">
|
|
Subject
|
|
</div>
|
|
<p className="text-base-content">Download</p>
|
|
</div>
|
|
<ArrowDownTrayIcon className="size-6" />
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default Practical;
|