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

Implement the support page on the employer dashboard #212

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
22 changes: 15 additions & 7 deletions src/app/dashboard/employer/components/employer-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import profilePic from "@/public/img/dashboardProfile.svg";
import homeIcon from "@/public/img/tutor icon/homeDashboard.svg";
import jobIcon from "@/public/img/permanent-job.svg";
import notificationIcon from "@/public/img/tutor icon/messageDashboard.svg";
import supportIcon from "@/public/img/supportIcon.svg";
import paymentIcon from "@/public/img/tutor icon/walletDashboard.svg";
import { DashBoardContext } from "@/app/useContext/dashboardContext";
import ChatBotButton from "@/components/ChatBotButton";


interface NavItemProps {
icon: ReactNode;
label: string;
Expand Down Expand Up @@ -85,17 +87,23 @@ export function Sidebar() {
onClick={() => onSectionChange("notifications")}
/>
<NavItem
icon={
<Image src={paymentIcon} alt="Payment" height={20} width={20} />
}
label="Payments"
active={activeSection === "payments"}
onClick={() => onSectionChange("payments")}
icon={<Image src={supportIcon} alt="Support" height={20} width={20} />}
label="Support"
active={activeSection === "support"}
onClick={() => onSectionChange("support")}
/>
<NavItem
icon={
<Image src={paymentIcon} alt="Payment" height={20} width={20} />
}
label="Payments"
active={activeSection === "payments"}
onClick={() => onSectionChange("payments")}
/>

<ChatBotButton />
</nav>
</div>
</aside>
);
}
}
5 changes: 4 additions & 1 deletion src/app/dashboard/employer/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DashBoardContext } from "@/app/useContext/dashboardContext";
import JobOpening from "./job-openings/job-openings";
import Notifications from "./notifications/notifications";
import Profile from "./profile/profile";
import Support from "./support/page";
import Payment from "./payment/payment";

function Page() {
Expand All @@ -20,9 +21,11 @@ function Page() {
case "notifications":
return <Notifications />;
case "profile":
return <Profile />;
return <Profile />;
case "payments":
return <Payment />;
case "support":
return <Support />;
default:
return <EmployerDashboard />;
}
Expand Down
172 changes: 172 additions & 0 deletions src/app/dashboard/employer/support/components/SupportDashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { SupportSection } from "./support-section";
import { ActionHistoryTable } from "./action-history-table";

// content data for support items
const supportItems = [
{
id: "course-creation",
description: "Course Creation Guide (How to structure, upload, and edit courses)",
content: `1. Structuring Your Course
• Define Objectives: Identify target audience & learning outcomes.
• Create Outline: Divide into modules (Introduction, Core Lessons, Assessments, Conclusion).
• Choose Formats: Video lectures, PDFs, quizzes, assignments, and discussion forums.

2. Uploading Your Course
• Upload Content: Ensure high-quality videos, structured lessons, and interactive elements.
• Set Pricing: Free, one-time payment, or subscription model.

3. Editing & Managing
• Update Content: Keep lessons relevant, improve UX, and add new resources.
• Track Progress: Use analytics to monitor engagement, respond to questions.
• Enhance Accessibility: Optimize video quality, add captions.

4. Launch & Promotion
• Pre-Launch: Build an email list, offer early access, create a landing page.
• Marketing: Use social media ads, SEO, influencers, and webinars.
• Optimize: Gather feedback, offer bonuses, and build a learner community.`,
},
{
id: "earnings-payments",
description: "Earnings & Payments (How earnings are calculated & withdrawal process)",
content: `1. How Earnings are Calculated
• Revenue Model: You receive 70% of the course price for direct sales.
• Promotional Sales: Varying percentages based on promotion type (platform-wide sales: 60%, affiliate sales: 50%).
• Bundle Earnings: Prorated based on your course's contribution to the bundle.

2. Payment Schedule
• Processing Period: Payments are calculated at the end of each month.
• Holding Period: 30-day holding period for all transactions to account for refunds.
• Release Dates: Funds become available for withdrawal on the 15th of each month.

3. Withdrawal Process
• Minimum Threshold: $50 minimum withdrawal amount.
• Payment Methods: Direct bank transfer, PayPal, or cryptocurrency options.
• Setup Requirements: Complete tax forms and verify your identity before withdrawal.
• Processing Time: 3-5 business days for standard transfers, 1-2 days for expedited options.

4. Tax Considerations
• 1099 Forms: Provided annually for earnings over $600.
• International Creators: May be subject to withholding based on tax treaties.
• Documentation: Keep records of all course-related expenses for tax deductions.`,
},
{
id: "student-engagement",
description: "Student Engagement Tips (How to improve student interaction & ratings)",
content: `1. Creating Interactive Content
• Discussion Prompts: Add thought-provoking questions at the end of each section.
• Assignments: Include practical exercises that apply learned concepts.
• Live Sessions: Schedule monthly Q&A or workshop sessions.

2. Responsive Communication
• Response Time: Aim to answer questions within 24 hours.
• Welcome Message: Send a personalized message to new students.
• Announcement Updates: Share news, additional resources, and industry updates.

3. Building Community
• Student Forums: Create a dedicated space for peer-to-peer interaction.
• Study Groups: Facilitate collaborative learning opportunities.
• Success Spotlights: Showcase student achievements and case studies.

4. Gathering and Implementing Feedback
• Mid-Course Surveys: Collect feedback while students are actively engaged.
• Completion Follow-ups: Send requests for reviews after course milestones.
• Iterative Improvement: Update content based on common questions and suggestions.
• Personal Touch: Add video responses to address common questions.`,
},
{
id: "technical-issues",
description: "Technical Issues (Troubleshooting course uploads, media files, etc.)",
content: `1. Video Upload Problems
• Supported Formats: MP4, MOV, and AVI with H.264 encoding.
• Size Limitations: Maximum file size of 4GB per video.
• Resolution Requirements: Minimum 720p (1280x720) resolution.
• Compression Tips: Use HandBrake or Adobe Media Encoder to optimize file size.

2. Audio Quality Issues
• Format Requirements: MP3 or AAC at 128kbps or higher.
• Background Noise: Use noise reduction software before uploading.
• Volume Levels: Maintain consistent -12dB to -6dB levels throughout.

3. Document and Supplement Materials
• Supported File Types: PDF, DOCX, XLSX, PPTX up to 100MB.
• Accessibility Tips: Ensure documents are formatted with proper headings and alt text.
• Template Usage: Utilize our branded templates for consistent appearance.

4. Platform Compatibility
• Browser Support: Chrome, Firefox, Safari, and Edge (latest versions).
• Mobile Optimization: Test content on iOS and Android devices.
• Connection Issues: Minimum 5Mbps upload speed recommended for reliable uploads.

5. Getting Help
• Priority Support: Available Monday-Friday, 9am-5pm EST.
• Ticket System: Submit detailed tickets with screenshots and device information.
• Live Assistance: Schedule a 15-minute troubleshooting call with our tech team.`,
},
{
id: "blockchain-integration",
description: "Blockchain Integration Help (Understanding on-chain payments & certifications)",
content: `1. Setting Up Cryptocurrency Payments
• Supported Currencies: ETH, BTC, USDC, and platform-native tokens.
• Wallet Connection: Connect your MetaMask, Coinbase Wallet, or WalletConnect.
• Fee Structure: 2% platform fee + network gas fees (paid by students).
• Payout Options: Automatic conversion to fiat or keep in cryptocurrency.

2. Blockchain Certifications
• Certificate Types: Course Completion, Skill Verification, and Achievement NFTs.
• Creation Process: Enable certifications in course settings and define requirements.
• Metadata Standards: Customize certificate appearance and embedded credentials.
• Verification System: Students receive a verifiable link and on-chain proof.

3. Smart Contract Integration
• Royalty Mechanisms: Set up secondary market royalties for resold certificates.
• Revenue Splitting: Configure automatic revenue distribution for collaborative courses.
• Conditional Access: Create token-gated content for premium or community members.

4. Technical Requirements
• Gas Optimization: Certificates are batch minted to reduce costs.
• Network Options: Ethereum mainnet, Polygon, Arbitrum, or Optimism.
• Resource Links: Developer documentation and API reference for custom integrations.

5. Compliance Considerations
• KYC Requirements: Verification needed for payments above $3,000.
• Tax Reporting: Automatic 1099-K generation for crypto earnings.
• Jurisdictional Limitations: Available in supported countries only.`,
},
];

// Sample data for action history
const actionHistoryItems = [
{
id: 1,
date: "12th Dec, 2025",
ticketId: "#12345",
issueCategory: "Payment Issue",
status: "Resolved" as const,
lastUpdate: "2025-02-19",
},
{
id: 2,
date: "12th Dec, 2025",
ticketId: "#67890",
issueCategory: "Course Upload Error",
status: "Pending" as const,
lastUpdate: "2025-02-17",
},
{
id: 3,
date: "12th Dec, 2025",
ticketId: "#24680",
issueCategory: "Student Dispute",
status: "Completed" as const,
lastUpdate: "2025-02-16",
},
];

export function SupportDashboard() {
return (
<div className="flex w-full flex-col space-y-8 bg-[#101110] px-5 py-5">
<SupportSection items={supportItems} />
<ActionHistoryTable items={actionHistoryItems} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";

interface ActionHistoryItem {
id: number;
date: string;
ticketId: string;
issueCategory: string;
status: "Resolved" | "Pending" | "Completed";
lastUpdate: string;
}

interface ActionHistoryTableProps {
items: ActionHistoryItem[];
}

export function ActionHistoryTable({ items }: ActionHistoryTableProps) {
const getStatusColor = (status: string) => {
switch (status) {
case "Resolved":
return "text-green-400";
case "Pending":
return "text-yellow-400";
case "Completed":
return "text-blue-400";
default:
return "text-gray-400";
}
};

return (
<div className="w-full rounded-lg text-white">
<h2 className="p-6 text-xl font-semibold">Action History Table</h2>
<div className="overflow-x-auto">
<Table>
<TableHeader>
<TableRow className="border-none bg-zinc-900 py-5 hover:bg-zinc-900">
<TableHead className="text-gray-400">SN</TableHead>
<TableHead className="text-gray-400">Date & Time</TableHead>
<TableHead className="text-gray-400">Ticket ID</TableHead>
<TableHead className="text-gray-400">Issue Category</TableHead>
<TableHead className="text-gray-400">Status</TableHead>
<TableHead className="text-gray-400">Last Update</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{items.map((item) => (
<TableRow
key={item.id}
className="border-zinc-800 hover:bg-zinc-900 text-[10px] md:text-xs"
>
<TableCell className="py-2 md:py-4 lg:py-5 xl:py-7">{item.id}</TableCell>
<TableCell className="py-2 md:py-4 lg:py-5 xl:py-7">{item.date}</TableCell>
<TableCell className="py-2 md:py-4 lg:py-5 xl:py-7">{item.ticketId}</TableCell>
<TableCell className="py-2 md:py-4 lg:py-5 xl:py-7">{item.issueCategory}</TableCell>
<TableCell className={`py-2 md:py-4 lg:py-5 xl:py-7 ${getStatusColor(item.status)}`}>
{item.status}
</TableCell>
<TableCell className="py-2 md:py-4 lg:py-5 xl:py-7">{item.lastUpdate}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
);
}
74 changes: 74 additions & 0 deletions src/app/dashboard/employer/support/components/support-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { motion, AnimatePresence } from "framer-motion";

interface SupportItem {
id: string;
description: string;
content: string;
}

interface SupportSectionProps {
items: SupportItem[];
}

export function SupportSection({ items }: SupportSectionProps) {
const [expandedItems, setExpandedItems] = useState<Record<string, boolean>>(
{}
);

const toggleItem = (id: string) => {
setExpandedItems((prev) => ({
...prev,
[id]: !prev[id],
}));
};

return (
<div className="w-full rounded-lg text-white">
<h2 className="pb-6 text-sm font-semibold">Support</h2>
<div className="flex flex-col">
{items.map((item, index) => (
<div key={item.id} className="flex flex-col">
<div className="flex items-center justify-between px-4 md:px-6 py-4 transition-colors duration-200">
<div className="flex flex-col">
<p className="text-sm text-gray-300">{item.description}</p>
</div>
<Button
variant="outline"
size="sm"
className="ml-4 px-3 py-1.5 w-20 rounded-full border-zinc-700 bg-zinc-800 p-0 text-white hover:bg-zinc-700 hover:text-white"
onClick={() => toggleItem(item.id)}
>
<span className="flex text-xs">
{expandedItems[item.id] ? "Collapse" : "Expand"}
</span>
</Button>
</div>
<AnimatePresence>
{expandedItems[item.id] && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="overflow-hidden"
>
<div className="px-4 md:px-6 pb-4">
<div className="rounded-md bg-zinc-800 p-4">
<p className="text-sm text-gray-300 whitespace-pre-line leading-8">
{item.content}
</p>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
{index < items.length - 1 && <div className="h-px bg-zinc-800" />}
</div>
))}
</div>
</div>
);
}
Loading
Loading