feat: update footer and navbar links, enhance button styles, and improve calendar layout

This commit is contained in:
Kemas M. Aryadary Rasyad
2026-08-04 12:20:53 +07:00
parent 60061e5c34
commit aee5124a2d
9 changed files with 144 additions and 119 deletions
+9 -9
View File
@@ -1,25 +1,23 @@
import { Link } from 'react-router-dom';
import { FaInstagram, FaLinkedin, FaRegEnvelope } from "react-icons/fa"; import { FaInstagram, FaLinkedin, FaRegEnvelope } from "react-icons/fa";
import logoHumic from "../assets/logo.png"; import logoHumic from "../assets/logo.png";
const internshipLinks = [ const internshipLinks = [
{ label: "Beranda", path: "/" }, { label: "Beranda", path: "/" },
{ label: "Tentang", path: "/about-us" }, { label: "Tentang", path: "/about-us" },
{ label: "Life At Humic", path: "" }, { label: "Life At Humic", path: "/internships" },
{ label: "Our Developer", path: "/our-developer" } { label: "Our Developer", path: "/our-developer" }
]; ];
const externalLinks = [ const externalLinks = [
{ label: "Humic Website", href: "https://humic.telkomuniversity.ac.id/" }, { label: "Humic Website", href: "https://humic.telkomuniversity.ac.id/" },
{ label: "Our Activity", href: "https://humic.telkomuniversity.ac.id/humicinmedia/" }, { label: "Our Activity", href: "https://humic.telkomuniversity.ac.id/humicinmedia/" },
{ label: "Life At Humic", href: "" }, { label: "Life At Humic", href: "https://humic.telkomuniversity.ac.id/" },
// { label: "Our Developer", href: "#" },
]; ];
const socials = [ const socials = [
{ label: "Instagram", icon: FaInstagram, href: "https://www.instagram.com/humicengineering/" }, { label: "Instagram", icon: FaInstagram, href: "https://www.instagram.com/humicengineering/" },
{ label: "LinkedIn", icon: FaLinkedin, href: "https://www.linkedin.com/company/humic-engineering/" }, { label: "LinkedIn", icon: FaLinkedin, href: "https://www.linkedin.com/company/humic-engineering/" },
{ label: "Email", icon: FaRegEnvelope, href: "" }, { label: "Email", icon: FaRegEnvelope, href: "mailto:humic@telkomuniversity.ac.id" },
]; ];
export function FooterIntern() { export function FooterIntern() {
@@ -45,7 +43,7 @@ export function FooterIntern() {
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
aria-label={label} aria-label={label}
className="w-10 h-10 border rounded-full bg-gray-100 flex items-center justify-center text-gray-600 hover:bg-red-50 hover:text-red-600 transition-colors" className="w-10 h-10 border rounded-full bg-gray-100 flex items-center justify-center text-gray-600 hover:bg-red-50 hover:text-red-800 transition-colors"
> >
<Icon className="w-4 h-4" /> <Icon className="w-4 h-4" />
</a> </a>
@@ -60,12 +58,14 @@ export function FooterIntern() {
<ul className="flex flex-col gap-0.5 font-semibold"> <ul className="flex flex-col gap-0.5 font-semibold">
{internshipLinks.map(({ label, path }) => ( {internshipLinks.map(({ label, path }) => (
<li key={label}> <li key={label}>
<Link <a
to={path} href={path}
target="_blank"
rel="noopener noreferrer"
className="text-[12.5px] text-gray-600 hover:text-red-800 transition-colors" className="text-[12.5px] text-gray-600 hover:text-red-800 transition-colors"
> >
{label} {label}
</Link> </a>
</li> </li>
))} ))}
</ul> </ul>
+4 -4
View File
@@ -59,19 +59,19 @@ const Navbar = () => {
<div className="hidden md:flex items-center gap-8 text-[18px] font-semibold"> <div className="hidden md:flex items-center gap-8 text-[18px] font-semibold">
<button <button
onClick={() => navigate("/about-us")} onClick={() => navigate("/about-us")}
className="hover:text-gray-600 transition cursor-pointer" className="hover:text-blue-600 transition cursor-pointer"
> >
About Us About Us
</button> </button>
<button <button
onClick={handleContactClick} onClick={handleContactClick}
className="hover:text-gray-600 transition cursor-pointer" className="hover:text-blue-600 transition cursor-pointer"
> >
Contact Us Contact Us
</button> </button>
<button <button
onClick={() => navigate("/internships")} onClick={() => navigate("/internships")}
className="hover:text-gray-600 transition cursor-pointer" className="hover:text-grblueay-600 transition cursor-pointer"
> >
Internship Internship
</button> </button>
@@ -80,7 +80,7 @@ const Navbar = () => {
onClick={() => { onClick={() => {
navigate("/login-internify"); navigate("/login-internify");
}} }}
className="hover:text-red-600 transition cursor-pointer" className="hover:text-blue-600 transition cursor-pointer"
> >
Portal LMS Portal LMS
</button> </button>
+41 -20
View File
@@ -103,11 +103,13 @@ export default function HomeCalendar() {
return ( return (
<div className="box"> <div className="box">
<div className="flex flex-col py-4">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-4 px-6"> <div className="flex items-center justify-between mb-4 px-13">
<h2 className="font-bold text-font"> <h2 className="font-bold text-font">
{MONTH_NAMES[currentMonth]} {currentYear} {MONTH_NAMES[currentMonth]} {currentYear}
</h2> </h2>
<div className="flex items-center"> <div className="flex items-center">
<button <button
onClick={prevMonth} onClick={prevMonth}
@@ -116,6 +118,7 @@ export default function HomeCalendar() {
> >
<ChevronLeft className="w-4 h-4 text-gray-500" /> <ChevronLeft className="w-4 h-4 text-gray-500" />
</button> </button>
<button <button
onClick={nextMonth} onClick={nextMonth}
className="p-1 rounded hover:bg-gray-100 transition-colors" className="p-1 rounded hover:bg-gray-100 transition-colors"
@@ -126,34 +129,46 @@ export default function HomeCalendar() {
</div> </div>
</div> </div>
<div className="grid grid-cols-7 mb-1 px-5"> <div className="grid grid-cols-7 mb-1 px-10 md:px-0">
{DAY_LABELS.map(day => ( {DAY_LABELS.map((day) => (
<div key={day} className="text-center text-xs text-gray-400 font-medium py-1"> <div
key={day}
className="text-center text-xs text-gray-400 font-medium py-1"
>
{day} {day}
</div> </div>
))} ))}
</div> </div>
<div className="grid grid-cols-7 px-5"> <div className="grid grid-cols-7 px-10 md:px-0">
{/* Trailing days from prev month */} {/* Trailing days from previous month */}
{trailingDays.map(day => ( {trailingDays.map((day) => (
<div key={`prev-${day}`} className="text-center py-2"> <div key={`prev-${day}`} className="text-center py-2">
<span className="text-xs text-gray-300">{day}</span> <span className="text-xs text-gray-400">{day}</span>
</div> </div>
))} ))}
{currentDays.map(day => ( {currentDays.map((day) => (
<div key={day} className="flex justify-center items-center py-1"> <div
key={day}
className="flex justify-center items-center py-1"
>
<div className="w-7 flex items-center justify-center"> <div className="w-7 flex items-center justify-center">
{isToday(day) ? ( {isToday(day) ? (
<span className="w-8 h-7 flex items-center justify-center border-b-2 text-xs font-semibold"> <span className="w-8 h-7 flex items-center justify-center text-red border-b-2 border-red text-xs font-semibold">
{day} {day}
</span> </span>
) : ( ) : (
<span <span
className={`w-full h-7 flex items-center justify-center text-xs className={`w-full h-7 flex items-center justify-center text-xs
${isBold(day) ? 'font-bold text-gray-800' : 'text-gray-700'} ${isBold(day)
${hasDeadline(day) ? 'bg-red text-white rounded-full' : ''} ? "font-bold text-gray-800"
: "text-gray-700"
}
${hasDeadline(day)
? "bg-red text-white rounded-full"
: ""
}
transition-colors`} transition-colors`}
> >
{day} {day}
@@ -164,34 +179,40 @@ export default function HomeCalendar() {
))} ))}
{/* Leading days from next month */} {/* Leading days from next month */}
{leadingDays.map(day => ( {leadingDays.map((day) => (
<div key={`next-${day}`} className="text-center py-2"> <div key={`next-${day}`} className="text-center py-2">
<span className="text-xs text-gray-300">{day}</span> <span className="text-xs text-gray-400">{day}</span>
</div> </div>
))} ))}
</div> </div>
{/* Divider */} {/* Divider */}
<hr className="my-3 border-box-border" /> <hr className="my-1.5 border-box-border" />
{/* Upcoming Deadlines */} {/* Upcoming Deadlines */}
<div className='px-5 mt-2'> <div className="px-8 mt-2">
<p className="text-[10px] font-semibold text-font uppercase tracking-widest mb-2"> <p className="text-[10px] font-semibold text-font uppercase tracking-widest mb-2">
Upcoming Deadlines Upcoming Deadlines
</p> </p>
{upcomingDeadlines.length > 0 ? ( {upcomingDeadlines.length > 0 ? (
<ul className="flex flex-col gap-1"> <ul className="flex flex-col gap-1">
{upcomingDeadlines.map((d, i) => ( {upcomingDeadlines.map((d, i) => (
<li key={i} className="flex items-center gap-2"> <li key={i} className="flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-red flex-shrink-0" /> <span className="w-2 h-2 rounded-full bg-red flex-shrink-0" />
<span className="text-xs text-font-shade">{formatDate(d.date)} - {d.label}</span> <span className="text-xs text-font-shade">
{formatDate(d.date)} - {d.label}
</span>
</li> </li>
))} ))}
</ul> </ul>
) : ( ) : (
<p className="text-[11px] text-font-shade">No upcoming deadlines this month.</p> <p className="text-[11px] text-font-shade">
No upcoming deadlines this month.
</p>
)} )}
</div> </div>
</div> </div>
) </div>
);
} }
@@ -151,7 +151,7 @@ export default function CertificateAvailable({ project, certificate, templateUrl
<button <button
onClick={handleDownloadPdf} onClick={handleDownloadPdf}
disabled={downloadingPdf} disabled={downloadingPdf}
className="flex items-center justify-center gap-2 w-full bg-red-700 hover:bg-red-800 active:scale-95 transition-all text-white font-semibold py-2 rounded-xl text-sm" className="flex items-center justify-center gap-2 w-full bg-red-700 hover:bg-red-800 active:scale-95 transition-all text-white font-semibold py-2 rounded-xl text-sm hover:cursor-pointer"
> >
<Download className="w-4 h-4" /> <Download className="w-4 h-4" />
{downloadingPdf ? "Memproses" : "Unduh Sertifikat"} {downloadingPdf ? "Memproses" : "Unduh Sertifikat"}
@@ -160,7 +160,7 @@ export default function CertificateAvailable({ project, certificate, templateUrl
{/* Bagikan ke LinkedIn */} {/* Bagikan ke LinkedIn */}
<button <button
onClick={handleShareLinkedIn} onClick={handleShareLinkedIn}
className="flex items-center justify-center gap-2 w-full bg-[#0A66C2] hover:bg-[#004182] active:scale-95 transition-all text-white font-semibold py-2 rounded-xl text-sm" className="flex items-center justify-center gap-2 w-full bg-[#0A66C2] hover:bg-[#004182] active:scale-95 transition-all text-white font-semibold py-2 rounded-xl text-sm hover:cursor-pointer"
> >
{/* LinkedIn icon */} {/* LinkedIn icon */}
<svg className="w-4 h-4 fill-white" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <svg className="w-4 h-4 fill-white" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
@@ -174,12 +174,13 @@ export default function CertificateAvailable({ project, certificate, templateUrl
<button <button
onClick={handleDownloadImage} onClick={handleDownloadImage}
disabled={downloadingImg} disabled={downloadingImg}
className="flex flex-col items-center justify-center gap-1.5 border border-card-outline hover:bg-gray-50 active:scale-95 transition-all text-red-700 font-medium py-1 md:py-3.5 rounded-xl text-sm"> className="flex flex-col items-center justify-center gap-1.5 border border-card-outline hover:bg-gray-50 active:scale-95 transition-all text-red-700 font-medium py-1 md:py-3.5 rounded-xl text-sm hover:cursor-pointer"
>
<Printer className="w-4 h-4 md:w-5 md:h-5" /> <Printer className="w-4 h-4 md:w-5 md:h-5" />
<span className="text-xs md:text-sm">{downloadingImg ? "Memproses" : "Cetak"}</span> <span className="text-xs md:text-sm">{downloadingImg ? "Memproses" : "Cetak"}</span>
</button> </button>
<button <button
className="flex flex-col items-center justify-center gap-1.5 border border-card-outline hover:bg-gray-50 active:scale-95 transition-all text-red-700 font-medium py-1 md:py-3.5 rounded-xl text-sm" className="flex flex-col items-center justify-center gap-1.5 border border-card-outline hover:bg-gray-50 active:scale-95 transition-all text-red-700 font-medium py-1 md:py-3.5 rounded-xl text-sm hover:cursor-pointer"
onClick={() => { onClick={() => {
navigator.clipboard.writeText(`${window.location.origin}/verify-certificate/${certificate.uuid}`); navigator.clipboard.writeText(`${window.location.origin}/verify-certificate/${certificate.uuid}`);
customToast.success("Link berhasil disalin!", "Link sudah disalin ke clipboard"); customToast.success("Link berhasil disalin!", "Link sudah disalin ke clipboard");
@@ -20,7 +20,7 @@ const HomeProjectList = () => {
if (error) return <p className="text-red-500 text-sm">{error}</p>; if (error) return <p className="text-red-500 text-sm">{error}</p>;
return ( return (
<div className=''> <div>
<h2 className="text-lg font-semibold text-font-shade mb-5">Projects</h2> <h2 className="text-lg font-semibold text-font-shade mb-5">Projects</h2>
{projects.length === 0 ? ( {projects.length === 0 ? (
@@ -8,7 +8,7 @@ const HomeMentorPage = () => {
<HomeHeader /> <HomeHeader />
<div className="flex flex-col gap-5"> <div className="flex flex-col gap-5">
<div className=""> <div className="">
<div className="bg-white border border-box-border rounded-xl p-6"> <div>
<HomeMentorProject /> <HomeMentorProject />
</div> </div>
</div> </div>
@@ -28,8 +28,8 @@ const HomeMentorProject = () => {
return ( return (
<div className='flex flex-col'> <div className='flex flex-col box'>
<div className='flex flex-row justify-between mb-3 items-center'> <div className='flex flex-row justify-between mb-5 items-center'>
<h2 className="text-lg font-semibold text-gray-800">Projects</h2> <h2 className="text-lg font-semibold text-gray-800">Projects</h2>
<button <button
className='bg-card p-1.5 rounded-lg font-bold hover:bg-card-hover border border-card-outline' className='bg-card p-1.5 rounded-lg font-bold hover:bg-card-hover border border-card-outline'
+6 -6
View File
@@ -23,13 +23,13 @@ async function ensureFontsLoaded(): Promise<void> {
// LAYOUT DEFAULT SERTIFIKAT YANG AKAN DIGENERATE // LAYOUT DEFAULT SERTIFIKAT YANG AKAN DIGENERATE
const LAYOUT = { const LAYOUT = {
internName: { x: 0.54, y: 0.47, size: 130, font: "Great Vibes", color: "#800000" }, internName: { x: 0.56, y: 0.47, size: 130, font: "Great Vibes", color: "#800000" },
internNameSmall: { x: 0.82, y: 0.889, size: 47, font: "Great Vibes", color: "#090909" }, internNameSmall: { x: 0.82, y: 0.88, size: 42, font: "Great Vibes", color: "#090909" },
userposition: { x: 0.855, y: 0.557, size: 46, font: "Grenze", color: "#800000" }, userposition: { x: 0.85, y: 0.557, size: 46, font: "Grenze", color: "#800000" },
duration: { x: 0.7, y: 0.615, size: 48, font: "Grenze", color: "#090909" }, duration: { x: 0.7, y: 0.615, size: 48, font: "Grenze", color: "#090909" },
certNo: { x: 0.56, y: 0.305, size: 50, font: "Grenze", color: "#090909" }, certNo: { x: 0.56, y: 0.305, size: 50, font: "Grenze", color: "#090909" },
certNoSmall: { x: 0.827, y: 0.92, size: 32, font: "Grenze", color: "#090909"}, certNoSmall: { x: 0.827, y: 0.905, size: 30, font: "Grenze", color: "#090909"},
qr: { x: 0.772, y: 0.715, size: 0.103 }, qr: { x: 0.771, y: 0.715, size: 0.103 },
}; };
// HELPER: kurangi ukuran font 25% jika nama melebihi 22 karakter (termasuk spasi) // HELPER: kurangi ukuran font 25% jika nama melebihi 22 karakter (termasuk spasi)
@@ -75,7 +75,7 @@ export async function generateCertificate(
}; };
text(LAYOUT.internName, internName); text(LAYOUT.internName, internName);
text(LAYOUT.internNameSmall, internName); text(LAYOUT.internNameSmall, internName.trim().toLowerCase());
text(LAYOUT.userposition, userposition); text(LAYOUT.userposition, userposition);
text(LAYOUT.duration, ProjectDuration); text(LAYOUT.duration, ProjectDuration);
text(LAYOUT.certNo, certificateNo); text(LAYOUT.certNo, certificateNo);
+4 -1
View File
@@ -57,7 +57,7 @@
background-color: var(--color-box-primary); background-color: var(--color-box-primary);
border-radius: 20px; border-radius: 20px;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
padding: 32px; padding:12px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -2px rgba(0, 0, 0, 0.1); 0 2px 4px -2px rgba(0, 0, 0, 0.1);
} }
@@ -135,6 +135,9 @@ dialog.custom-dialog::backdrop {
padding-bottom: 1.25rem; padding-bottom: 1.25rem;
} }
.box {
padding: 32px;
}
.main-content { .main-content {
padding-block: calc(var(--spacing) * 10); padding-block: calc(var(--spacing) * 10);
} }