Skip to content

Commit

Permalink
Merge pull request #56 from OthmanImam/feature/HelpGuide
Browse files Browse the repository at this point in the history
Feature/help guide
  • Loading branch information
BigBen-7 authored Jan 28, 2025
2 parents ecd4b1e + fa222d9 commit 50de1b4
Show file tree
Hide file tree
Showing 13 changed files with 1,322 additions and 214 deletions.
72 changes: 65 additions & 7 deletions frontend/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
@tailwind components;
@tailwind utilities;

:root {
--background: #ffffff;
--foreground: #171717;
}

@media (prefers-color-scheme: white) {
:root {
--background: #0a0a0a;
Expand All @@ -15,7 +10,70 @@
}

body {
color: var(--foreground);
background: var(--background);
font-family: Arial, Helvetica, sans-serif;
}

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
77 changes: 77 additions & 0 deletions frontend/app/helpContent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
export const helpContent = {
gettingStarted: [
{
title: "Creating Your Account",
content:
"Sign up with your email or social media account to get started. Complete your profile to personalize your experience.",
},
{
title: "Basic Navigation",
content:
"Use the top navigation bar to move between different sections. The sidebar contains quick access to your favorite features.",
},
{
title: "First Steps",
content:
"Start by exploring the song library, create your first playlist, or join a music quiz to test your knowledge.",
},
],
features: [
{
type: "header",
title: "How To Play",
subtitle: "Guess the Wordle in 6 tries.",
},
{
type: "rules",
items: [
"Each guess must be a valid 5-letter word.",
"The color of the tiles will change to show how close your guess was to the word.",
],
},
{
type: "examples",
title: "Examples",
items: [
{
word: ["W", "O", "R", "D", "Y"],
correctIndex: 0,
explanation: " is in the word and in the correct spot.",
},
{
word: ["L", "I", "G", "H", "T"],
presentIndex: 1,
explanation: " is in the word but in the wrong spot.",
},
{
word: ["R", "O", "G", "U", "E"],
absentIndex: 3,
// correctIndex: 0,
explanation: " is not in the word in any spot.",
},
],
},
{
type: "footer",
content:
"A new puzzle is released daily at midnight. If you haven't already, you can sign up for our daily reminder email.",
},
],
troubleshooting: [
{
title: "Connection Issues",
content:
"If you're experiencing connection problems, check your internet connection and try refreshing the page.",
},
{
title: "Audio Problems",
content: "Ensure your device's volume is turned on and you've granted necessary permissions for audio playback.",
},
{
title: "Account Recovery",
content: "Forgot your password? Use the 'Forgot Password' link on the login page to reset it via email.",
},
],
}


21 changes: 21 additions & 0 deletions frontend/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": false,
"tailwind": {
"config": "tailwind.config.mjs",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
181 changes: 181 additions & 0 deletions frontend/components/HelpGuide.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
"use client"

import React from "react"
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { BookOpen, Settings, Gamepad2 } from "lucide-react"
import Link from "next/link"
import { helpContent } from "../app/helpContent"

// Component for rendering individual letter tiles
function LetterTile({ letter, state = "absent" }) {
const baseStyles = "w-8 h-8 flex items-center justify-center text-base font-bold border-2 select-none"
const stateStyles = {
correct: "bg-green-600 text-white border-green-600",
present: "bg-yellow-500 text-white border-yellow-500",
absent: "dark:bg-gray-900 dark:text-white dark:border-gray-600 bg-gray-700 text-white border-gray-300",
}

return <div className={`${baseStyles} ${stateStyles[state]}`}>{letter}</div>
}

// Component for rendering a word example with colored tiles
function WordExample({ word, correctIndex, presentIndex, absentIndex }) {
return (
<div className="flex gap-1">
{word.map((letter, index) => (
<LetterTile
key={index}
letter={letter}
state={index === correctIndex ? "correct" : index === presentIndex ? "present" : index === absentIndex ? "absent" : " "}
/>
))}
</div>
)
}

// Main HelpGuide component
export function HelpGuide({ isOpen, onClose }) {
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="sm:max-w-[600px] max-h-[80vh] overflow-y-auto">
{/* Dialog header */}
<DialogHeader>
<DialogTitle className="text-2xl font-bold">Help Guide</DialogTitle>
</DialogHeader>

{/* Tab navigation */}
<Tabs defaultValue="getting-started" className="mt-4">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="getting-started" className="flex items-center gap-2">
<BookOpen className="h-4 w-4" />
<span className="hidden sm:inline">Getting Started</span>
</TabsTrigger>
<TabsTrigger value="features" className="flex items-center gap-2">
<Gamepad2 className="h-4 w-4" />
<span className="hidden sm:inline">How to Play</span>
</TabsTrigger>
<TabsTrigger value="troubleshooting" className="flex items-center gap-2">
<Settings className="h-4 w-4" />
<span className="hidden sm:inline">Troubleshooting</span>
</TabsTrigger>
</TabsList>

{/* Getting Started tab content */}
<TabsContent value="getting-started" className="mt-4">
<div className="text-sm text-muted-foreground mb-4">
Welcome! Let's help you get started with our platform.
</div>
<Accordion type="single" collapsible className="w-full hover:no-underline">
{helpContent.gettingStarted.map((item, index) => (
<AccordionItem key={index} value={`item-${index}`}>
<AccordionTrigger className="hover:no-underline">{item.title}</AccordionTrigger>
<AccordionContent>{item.content}</AccordionContent>
</AccordionItem>
))}
</Accordion>
</TabsContent>

{/* How to Play tab content */}
<TabsContent value="features" className="mt-4">
<div className="text-sm text-muted-foreground mb-4">Learn how to play Wordle.</div>
<div className="space-y-6">
{helpContent.features.map((section, index) => {
switch (section.type) {
// Header section
case "header":
return (
<div key={index}>
<h2 className="text-2xl font-bold mb-2">{section.title}</h2>
<p className="text-base mb-4">{section.subtitle}</p>
</div>
)
// Rules section
case "rules":
return (
<div key={index} className="space-y-2">
{section.items.map((item, itemIndex) => (
<p key={itemIndex} className="text-sm">
{item}
</p>
))}
</div>
)
// Examples section
case "examples":
return (
<div key={index} className="space-y-4">
<h3 className="text-lg font-semibold">{section.title}</h3>
{section.items.map((item, itemIndex) => (
<div key={itemIndex} className="space-y-2">
<WordExample
word={item.word}
correctIndex={item.correctIndex}
presentIndex={item.presentIndex}
absentIndex={item.absentIndex}
/>
<p className="text-sm">
<strong>{item.word[item.absentIndex || item.correctIndex || item.presentIndex || 0]}</strong>{" "}
{item.explanation}
</p>
</div>
))}
</div>
)
// Footer section
case "footer":
return (
<p key={index} className="text-sm text-muted-foreground">
{section.content.split("sign up").map((part, i) =>
i === 0 ? (
part
) : (
<React.Fragment key={i}>
<Link
href="#"
className="text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300 underline"
>
sign up
</Link>
{part}
</React.Fragment>
),
)}
</p>
)
default:
return null
}
})}
</div>
</TabsContent>

{/* Troubleshooting tab content */}
<TabsContent value="troubleshooting" className="mt-4">
<div className="text-sm text-muted-foreground mb-4">
Having issues? Find solutions to common problems here.
</div>
<Accordion type="single" collapsible className="w-full">
{helpContent.troubleshooting.map((item, index) => (
<AccordionItem key={index} value={`item-${index}`}>
<AccordionTrigger className="hover:no-underline">{item.title}</AccordionTrigger>
<AccordionContent>{item.content}</AccordionContent>
</AccordionItem>
))}
</Accordion>
</TabsContent>
</Tabs>

{/* Close button */}
<div className="mt-6 flex justify-end">
<Button variant="outline" onClick={onClose}>
Close Guide
</Button>
</div>
</DialogContent>
</Dialog>
)
}

Loading

0 comments on commit 50de1b4

Please sign in to comment.