full rework in vite
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { Route, Routes } from "react-router-dom"
|
||||
import Navigation from "@/components/navigation"
|
||||
import Footer from "@/components/footer"
|
||||
import Home from "@/pages/Home"
|
||||
import Topic from "@/pages/Topic"
|
||||
|
||||
export default function App() {
|
||||
const [showButton, setShowButton] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => setShowButton(window.scrollY > 300)
|
||||
window.addEventListener("scroll", handleScroll)
|
||||
return () => window.removeEventListener("scroll", handleScroll)
|
||||
}, [])
|
||||
|
||||
const scrollToTop = () => window.scrollTo({ top: 0, behavior: "smooth" })
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-[100dvh]">
|
||||
<Navigation />
|
||||
<main className="flex-1">
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/topic/:id" element={<Topic />} />
|
||||
</Routes>
|
||||
</main>
|
||||
{showButton && (
|
||||
<button
|
||||
onClick={scrollToTop}
|
||||
className="fixed bottom-10 right-10 bg-primary text-primary-foreground p-3 rounded-full shadow-lg hover:bg-primary-dark transition"
|
||||
>
|
||||
↑ Top
|
||||
</button>
|
||||
)}
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
CarouselNext,
|
||||
CarouselPrevious,
|
||||
} from "@/components/ui/carousel"
|
||||
import type { Topic } from "@/data/topics"
|
||||
|
||||
export default function TopicContent({ topic }: { topic: Topic }) {
|
||||
return (
|
||||
<section className="py-12 md:py-24 w-full">
|
||||
<div className="container mx-auto px-4 md:px-6">
|
||||
<h2 className="text-3xl font-bold mb-8">{topic.title}</h2>
|
||||
<p className="text-lg mb-8">{topic.description}</p>
|
||||
<div className="grid md:grid-cols-2 gap-16">
|
||||
{topic.items.map((item, itemIndex) => (
|
||||
<div key={itemIndex}>
|
||||
<h3 className="text-2xl font-bold mb-4">{item.title}</h3>
|
||||
<p className="text-muted-foreground mb-6">{item.description}</p>
|
||||
<div className="bg-background rounded-lg p-6 shadow-2xl my-4">
|
||||
<Carousel className="max-w px-8">
|
||||
<CarouselContent>
|
||||
<CarouselItem>
|
||||
<pre className="text-sm font-mono">
|
||||
<code className="text-pretty">{item.code}</code>
|
||||
</pre>
|
||||
</CarouselItem>
|
||||
<CarouselItem>
|
||||
<pre className="text-sm font-mono">
|
||||
<code className="text-pretty">{item.result}</code>
|
||||
</pre>
|
||||
</CarouselItem>
|
||||
</CarouselContent>
|
||||
<CarouselPrevious className="mx-6"/>
|
||||
<CarouselNext className="mx-6"/>
|
||||
</Carousel>
|
||||
</div>
|
||||
<p className="text-pretty">{item.explanation}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import { JSX, SVGProps } from "react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="bg-muted text-muted-foreground py-6">
|
||||
<div className="container mx-auto px-4 md:px-6 flex items-center justify-between">
|
||||
<p className="text-sm">© 2024 Quintavalle Pietro. All rights reserved.</p>
|
||||
<nav className="flex items-center gap-4">
|
||||
<Dialog>
|
||||
<DialogTrigger>Licence</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>MIT License</DialogTitle>
|
||||
<DialogDescription>
|
||||
<p className="font-bold">Copyright (c) 2024 Quintavalle Pietro</p>
|
||||
<p className="mt-2">
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
</p>
|
||||
<p>
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
</p>
|
||||
<p className="mt-2">
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
</p>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<a href="https://github.com/Quinta0" target="_blank" rel="noopener noreferrer"
|
||||
className="hover:underline">
|
||||
<GitHubIcon className="w-6 h-6"/>
|
||||
</a>
|
||||
<a href="mailto:0pietroquintavalle0@gmail.com" className="hover:underline">
|
||||
<GmailIcon className="w-6 h-6"/>
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/in/pietro-quintavalle-996b96267/" target="_blank"
|
||||
rel="noopener noreferrer" className="hover:underline">
|
||||
<LinkedInIcon className="w-6 h-6"/>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
function GitHubIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0"
|
||||
>
|
||||
<path d="M12 .5C5.48.5.5 5.48.5 12c0 5.08 3.29 9.35 7.85 10.86.58.1.79-.24.79-.54 0-.27-.01-.99-.01-1.94-3.19.69-3.86-1.54-3.86-1.54-.53-1.36-1.29-1.72-1.29-1.72-1.05-.72.08-.71.08-.71 1.16.08 1.77 1.2 1.77 1.2 1.03 1.77 2.69 1.26 3.34.96.1-.75.4-1.26.73-1.55-2.55-.29-5.23-1.28-5.23-5.72 0-1.26.45-2.29 1.2-3.1-.12-.29-.52-1.45.12-3.02 0 0 .97-.31 3.17 1.18.92-.26 1.91-.39 2.89-.39.98 0 1.97.13 2.89.39 2.2-1.49 3.17-1.18 3.17-1.18.64 1.57.24 2.73.12 3.02.75.81 1.2 1.84 1.2 3.1 0 4.46-2.69 5.43-5.25 5.71.41.35.78 1.03.78 2.08 0 1.5-.01 2.72-.01 3.08 0 .3.21.65.8.54C20.71 21.35 24 17.08 24 12c0-6.52-4.98-11.5-12-11.5z"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function GmailIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0"
|
||||
>
|
||||
<path d="M12 12.713l11.985-8.677a.868.868 0 0 0-.491-.148H.506c-.177 0-.344.055-.491.148L12 12.713zm0 1.431L.035 5.596A.875.875 0 0 0 0 6.125v11.75c0 .478.387.875.875.875h22.25c.478 0 .875-.387.875-.875V6.125a.875.875 0 0 0-.035-.529L12 14.144z"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function LinkedInIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0"
|
||||
>
|
||||
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.761 0 5-2.239 5-5v-14c0-2.761-2.239-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.5c-.966 0-1.75-.784-1.75-1.75s.784-1.75 1.75-1.75 1.75.784 1.75 1.75-.784 1.75-1.75 1.75zm13.5 12.5h-3v-5.5c0-1.379-1.121-2.5-2.5-2.5s-2.5 1.121-2.5 2.5v5.5h-3v-11h3v1.474c.809-1.161 2.201-1.974 3.5-1.974 2.481 0 4.5 2.019 4.5 4.5v7z"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import { Link } from "react-router-dom";
|
||||
import { topics } from "@/data/topics";
|
||||
import { JSX, SVGProps } from "react";
|
||||
|
||||
export default function Navigation() {
|
||||
return (
|
||||
<header className="bg-primary text-primary-foreground py-4 px-6 shadow">
|
||||
<div className="container mx-auto flex items-center justify-between">
|
||||
<Link to="/" className="flex items-center gap-2 font-bold text-xl">
|
||||
<CodeIcon className="w-6 h-6"/>
|
||||
Dot Java
|
||||
</Link>
|
||||
<nav className="hidden md:flex items-center gap-6">
|
||||
{topics.map((topic) => (
|
||||
<Link key={topic.id} to={`/topic/${topic.id}`} className="hover:underline">
|
||||
{topic.title}
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 512 512"
|
||||
enableBackground="23 23 23"
|
||||
xmlSpace="preserve"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path fill="#171717" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M240.000000,513.000000
|
||||
C160.019394,513.000000 80.538788,513.000000 1.029092,513.000000
|
||||
C1.029092,342.394379 1.029092,171.788727 1.029092,1.091547
|
||||
C171.563965,1.091547 342.127991,1.091547 512.846008,1.091547
|
||||
C512.846008,171.666565 512.846008,342.333252 512.846008,513.000000
|
||||
C422.122040,513.000000 331.311005,513.000000 240.000000,513.000000
|
||||
M410.993988,312.497375
|
||||
C410.656464,320.474792 410.875092,328.522644 409.875427,336.416199
|
||||
C407.066986,358.591736 395.828674,374.636627 374.031616,381.696930
|
||||
C360.300110,386.144745 346.144257,386.188507 332.139099,382.561066
|
||||
C314.212372,377.917847 301.829712,366.828979 296.220825,349.172028
|
||||
C293.632660,341.024353 292.780731,332.325165 291.074066,323.528076
|
||||
C278.871552,323.528076 265.968353,323.528076 252.056076,323.528076
|
||||
C253.064514,332.063293 253.489624,340.370422 255.100037,348.441040
|
||||
C260.761566,376.813599 275.974670,398.381897 302.717468,410.285675
|
||||
C331.966187,423.304871 362.237671,423.536865 392.339081,413.506226
|
||||
C415.206604,405.886169 431.804352,390.516083 441.814331,368.480042
|
||||
C448.760773,353.188080 450.558044,336.881256 450.544250,320.242584
|
||||
C450.483337,246.767456 450.518280,173.292236 450.518524,99.817055
|
||||
C450.518524,98.201042 450.518524,96.585030 450.518524,94.734009
|
||||
C411.417328,94.734009 372.851379,94.734009 334.226685,94.734009
|
||||
C334.226685,106.749191 334.226685,118.510406 334.226685,130.714798
|
||||
C359.846375,130.714798 385.238434,130.714798 410.481018,130.714798
|
||||
C410.747650,131.456650 410.950775,131.758057 410.950897,132.059509
|
||||
C410.974640,191.872437 410.984070,251.685364 410.993988,312.497375
|
||||
M87.691093,348.998718
|
||||
C64.397789,356.446655 60.637661,382.525238 66.682755,398.797058
|
||||
C73.876472,418.160767 99.387474,426.453217 119.434303,416.107788
|
||||
C133.284363,408.960266 139.973038,393.206451 136.584061,375.933624
|
||||
C133.839737,361.946350 126.024956,352.428772 112.140968,348.535126
|
||||
C104.306267,346.337982 96.337631,346.484802 87.691093,348.998718
|
||||
z"/>
|
||||
<path fill="#FCFCFC" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M410.993958,311.997833
|
||||
C410.984070,251.685364 410.974640,191.872437 410.950897,132.059509
|
||||
C410.950775,131.758057 410.747650,131.456650 410.481018,130.714798
|
||||
C385.238434,130.714798 359.846375,130.714798 334.226685,130.714798
|
||||
C334.226685,118.510406 334.226685,106.749191 334.226685,94.734009
|
||||
C372.851379,94.734009 411.417328,94.734009 450.518524,94.734009
|
||||
C450.518524,96.585030 450.518524,98.201042 450.518524,99.817055
|
||||
C450.518280,173.292236 450.483337,246.767456 450.544250,320.242584
|
||||
C450.558044,336.881256 448.760773,353.188080 441.814331,368.480042
|
||||
C431.804352,390.516083 415.206604,405.886169 392.339081,413.506226
|
||||
C362.237671,423.536865 331.966187,423.304871 302.717468,410.285675
|
||||
C275.974670,398.381897 260.761566,376.813599 255.100037,348.441040
|
||||
C253.489624,340.370422 253.064514,332.063293 252.056076,323.528076
|
||||
C265.968353,323.528076 278.871552,323.528076 291.074066,323.528076
|
||||
C292.780731,332.325165 293.632660,341.024353 296.220825,349.172028
|
||||
C301.829712,366.828979 314.212372,377.917847 332.139099,382.561066
|
||||
C346.144257,386.188507 360.300110,386.144745 374.031616,381.696930
|
||||
C395.828674,374.636627 407.066986,358.591736 409.875427,336.416199
|
||||
C410.875092,328.522644 410.656464,320.474792 410.993958,311.997833
|
||||
z"/>
|
||||
<path fill="#FDFDFD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M88.082108,348.899780
|
||||
C96.337631,346.484802 104.306267,346.337982 112.140968,348.535126
|
||||
C126.024956,352.428772 133.839737,361.946350 136.584061,375.933624
|
||||
C139.973038,393.206451 133.284363,408.960266 119.434303,416.107788
|
||||
C99.387474,426.453217 73.876472,418.160767 66.682755,398.797058
|
||||
C60.637661,382.525238 64.397789,356.446655 88.082108,348.899780
|
||||
z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline:
|
||||
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-4 py-2",
|
||||
sm: "h-9 rounded-md px-3",
|
||||
lg: "h-11 rounded-md px-8",
|
||||
icon: "h-10 w-10",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
|
||||
export { Button, buttonVariants }
|
||||
@@ -0,0 +1,79 @@
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Card.displayName = "Card"
|
||||
|
||||
const CardHeader = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardHeader.displayName = "CardHeader"
|
||||
|
||||
const CardTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLHeadingElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<h3
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-2xl font-semibold leading-none tracking-tight",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardTitle.displayName = "CardTitle"
|
||||
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
|
||||
const CardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||
))
|
||||
CardContent.displayName = "CardContent"
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex items-center p-6 pt-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = "CardFooter"
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
||||
@@ -0,0 +1,262 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import useEmblaCarousel, {
|
||||
type UseEmblaCarouselType,
|
||||
} from "embla-carousel-react"
|
||||
import { ArrowLeft, ArrowRight } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
type CarouselApi = UseEmblaCarouselType[1]
|
||||
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
||||
type CarouselOptions = UseCarouselParameters[0]
|
||||
type CarouselPlugin = UseCarouselParameters[1]
|
||||
|
||||
type CarouselProps = {
|
||||
opts?: CarouselOptions
|
||||
plugins?: CarouselPlugin
|
||||
orientation?: "horizontal" | "vertical"
|
||||
setApi?: (api: CarouselApi) => void
|
||||
}
|
||||
|
||||
type CarouselContextProps = {
|
||||
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
|
||||
api: ReturnType<typeof useEmblaCarousel>[1]
|
||||
scrollPrev: () => void
|
||||
scrollNext: () => void
|
||||
canScrollPrev: boolean
|
||||
canScrollNext: boolean
|
||||
} & CarouselProps
|
||||
|
||||
const CarouselContext = React.createContext<CarouselContextProps | null>(null)
|
||||
|
||||
function useCarousel() {
|
||||
const context = React.useContext(CarouselContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useCarousel must be used within a <Carousel />")
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
const Carousel = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement> & CarouselProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
orientation = "horizontal",
|
||||
opts,
|
||||
setApi,
|
||||
plugins,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const [carouselRef, api] = useEmblaCarousel(
|
||||
{
|
||||
...opts,
|
||||
axis: orientation === "horizontal" ? "x" : "y",
|
||||
},
|
||||
plugins
|
||||
)
|
||||
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
|
||||
const [canScrollNext, setCanScrollNext] = React.useState(false)
|
||||
|
||||
const onSelect = React.useCallback((api: CarouselApi) => {
|
||||
if (!api) {
|
||||
return
|
||||
}
|
||||
|
||||
setCanScrollPrev(api.canScrollPrev())
|
||||
setCanScrollNext(api.canScrollNext())
|
||||
}, [])
|
||||
|
||||
const scrollPrev = React.useCallback(() => {
|
||||
api?.scrollPrev()
|
||||
}, [api])
|
||||
|
||||
const scrollNext = React.useCallback(() => {
|
||||
api?.scrollNext()
|
||||
}, [api])
|
||||
|
||||
const handleKeyDown = React.useCallback(
|
||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (event.key === "ArrowLeft") {
|
||||
event.preventDefault()
|
||||
scrollPrev()
|
||||
} else if (event.key === "ArrowRight") {
|
||||
event.preventDefault()
|
||||
scrollNext()
|
||||
}
|
||||
},
|
||||
[scrollPrev, scrollNext]
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api || !setApi) {
|
||||
return
|
||||
}
|
||||
|
||||
setApi(api)
|
||||
}, [api, setApi])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return
|
||||
}
|
||||
|
||||
onSelect(api)
|
||||
api.on("reInit", onSelect)
|
||||
api.on("select", onSelect)
|
||||
|
||||
return () => {
|
||||
api?.off("select", onSelect)
|
||||
}
|
||||
}, [api, onSelect])
|
||||
|
||||
return (
|
||||
<CarouselContext.Provider
|
||||
value={{
|
||||
carouselRef,
|
||||
api: api,
|
||||
opts,
|
||||
orientation:
|
||||
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
||||
scrollPrev,
|
||||
scrollNext,
|
||||
canScrollPrev,
|
||||
canScrollNext,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={ref}
|
||||
onKeyDownCapture={handleKeyDown}
|
||||
className={cn("relative", className)}
|
||||
role="region"
|
||||
aria-roledescription="carousel"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</CarouselContext.Provider>
|
||||
)
|
||||
}
|
||||
)
|
||||
Carousel.displayName = "Carousel"
|
||||
|
||||
const CarouselContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const { carouselRef, orientation } = useCarousel()
|
||||
|
||||
return (
|
||||
<div ref={carouselRef} className="overflow-hidden">
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex",
|
||||
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
CarouselContent.displayName = "CarouselContent"
|
||||
|
||||
const CarouselItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const { orientation } = useCarousel()
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
role="group"
|
||||
aria-roledescription="slide"
|
||||
className={cn(
|
||||
"min-w-0 shrink-0 grow-0 basis-full",
|
||||
orientation === "horizontal" ? "pl-4" : "pt-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
CarouselItem.displayName = "CarouselItem"
|
||||
|
||||
const CarouselPrevious = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
React.ComponentProps<typeof Button>
|
||||
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
|
||||
const { orientation, scrollPrev, canScrollPrev } = useCarousel()
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
variant={variant}
|
||||
size={size}
|
||||
className={cn(
|
||||
"absolute h-8 w-8 rounded-full",
|
||||
orientation === "horizontal"
|
||||
? "-left-12 top-1/2 -translate-y-1/2"
|
||||
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
||||
className
|
||||
)}
|
||||
disabled={!canScrollPrev}
|
||||
onClick={scrollPrev}
|
||||
{...props}
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
<span className="sr-only">Previous slide</span>
|
||||
</Button>
|
||||
)
|
||||
})
|
||||
CarouselPrevious.displayName = "CarouselPrevious"
|
||||
|
||||
const CarouselNext = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
React.ComponentProps<typeof Button>
|
||||
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
|
||||
const { orientation, scrollNext, canScrollNext } = useCarousel()
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
variant={variant}
|
||||
size={size}
|
||||
className={cn(
|
||||
"absolute h-8 w-8 rounded-full",
|
||||
orientation === "horizontal"
|
||||
? "-right-12 top-1/2 -translate-y-1/2"
|
||||
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
||||
className
|
||||
)}
|
||||
disabled={!canScrollNext}
|
||||
onClick={scrollNext}
|
||||
{...props}
|
||||
>
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
<span className="sr-only">Next slide</span>
|
||||
</Button>
|
||||
)
|
||||
})
|
||||
CarouselNext.displayName = "CarouselNext"
|
||||
|
||||
export {
|
||||
type CarouselApi,
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
CarouselPrevious,
|
||||
CarouselNext,
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
||||
import { X } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Dialog = DialogPrimitive.Root
|
||||
|
||||
const DialogTrigger = DialogPrimitive.Trigger
|
||||
|
||||
const DialogPortal = DialogPrimitive.Portal
|
||||
|
||||
const DialogClose = DialogPrimitive.Close
|
||||
|
||||
const DialogOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<DialogPortal>
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
))
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName
|
||||
|
||||
const DialogHeader = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-1.5 text-center sm:text-left",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
DialogHeader.displayName = "DialogHeader"
|
||||
|
||||
const DialogFooter = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
DialogFooter.displayName = "DialogFooter"
|
||||
|
||||
const DialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-lg font-semibold leading-none tracking-tight",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
||||
|
||||
const DialogDescription = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
DialogPortal,
|
||||
DialogOverlay,
|
||||
DialogClose,
|
||||
DialogTrigger,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
{
|
||||
"sections": [
|
||||
{
|
||||
"id": "basics",
|
||||
"title": "Java Basics",
|
||||
"description": "Explore the fundamental concepts of the Java programming language, including data types, variables, operators, control structures, and methods.",
|
||||
"items": [
|
||||
{
|
||||
"title": "Data Types",
|
||||
"description": "Different data types in Java such as int, double, boolean, and String, allow you to store various kinds of data.",
|
||||
"code": "int x = 10;\ndouble y = 3.14;\nboolean isTrue = true;\nString name = \"John Doe\";",
|
||||
"explanation": "This code snippet demonstrates the declaration and initialization of variables with different data types: an integer, a double, a boolean, and a string.",
|
||||
"result": "The variables x, y, isTrue, and name are initialized with values 10, 3.14, true, and \"John Doe\", respectively."
|
||||
},
|
||||
{
|
||||
"title": "Variables",
|
||||
"description": "Variables in Java store data values that can be used and manipulated throughout the program.",
|
||||
"code": "int age = 25;\nString city = \"New York\";\ndouble salary = 50000.0;",
|
||||
"explanation": "This code shows how to declare variables of various types and initialize them with values. Variables store data that can be used and manipulated throughout the program.",
|
||||
"result": "The variables age, city, and salary are initialized with values 25, \"New York\", and 50000.0, respectively."
|
||||
},
|
||||
{
|
||||
"title": "Operators",
|
||||
"description": "Operators in Java are special symbols used to perform operations on variables and values.",
|
||||
"code": "int a = 10;\nint b = 5;\nint sum = a + b;\nint diff = a - b;\nint product = a * b;\nint quotient = a / b;",
|
||||
"explanation": "This example demonstrates the use of arithmetic operators in Java. It shows how to perform basic mathematical operations like addition, subtraction, multiplication, and division.",
|
||||
"result": "The variables sum, diff, product, and quotient are calculated as 15, 5, 50, and 2, respectively."
|
||||
},
|
||||
{
|
||||
"title": "Control Structures",
|
||||
"description": "Control structures like if-else, switch-case, and loops determine the flow of execution in a Java program.",
|
||||
"code": "int num = 10;\nif (num > 0) {\n System.out.println(\"Positive number\");\n} else {\n System.out.println(\"Non-positive number\");\n}\n\nswitch (num) {\n case 1:\n System.out.println(\"One\");\n break;\n case 10:\n System.out.println(\"Ten\");\n break;\n default:\n System.out.println(\"Other number\");\n}\n\nfor (int i = 0; i < 5; i++) {\n System.out.println(i);\n}",
|
||||
"explanation": "This snippet demonstrates the use of control structures in Java. The if-else statement checks if a number is positive. The switch-case statement executes different code blocks based on the value of the number. The for loop iterates from 0 to 4 and prints each value.",
|
||||
"result": "Output:\nPositive number\nTen\n0\n1\n2\n3\n4"
|
||||
},
|
||||
{
|
||||
"title": "Methods",
|
||||
"description": "Methods in Java are blocks of code that perform a specific task and can be called upon when needed.",
|
||||
"code": "public class Main {\n public static void main(String[] args) {\n greet(\"John\");\n }\n\n public static void greet(String name) {\n System.out.println(\"Hello, \" + name);\n }\n}",
|
||||
"explanation": "This code defines a class with a main method that calls another method named greet. The greet method takes a string parameter and prints a greeting message. Methods help organize code into reusable blocks.",
|
||||
"result": "Output:\nHello, John"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "oop",
|
||||
"title": "Java Object-Oriented Programming",
|
||||
"description": "Dive into the principles of object-oriented programming in Java, including classes, objects, inheritance, and encapsulation.",
|
||||
"items": [
|
||||
{
|
||||
"title": "Classes and Objects",
|
||||
"description": "Classes are blueprints for creating objects, which are instances of classes containing attributes and methods.",
|
||||
"code": "class Person {\n String name;\n int age;\n\n void introduce() {\n System.out.println(\"Hello, my name is \" + name);\n }\n}\n\nPerson p = new Person();\np.name = \"John\";\np.age = 30;\np.introduce();",
|
||||
"explanation": "This example defines a class named Person with two fields (name and age) and a method (introduce). An object of the Person class is created, its fields are assigned values, and the introduce method is called to print a message.",
|
||||
"result": "Output:\nHello, my name is John"
|
||||
},
|
||||
{
|
||||
"title": "Inheritance",
|
||||
"description": "Inheritance allows one class to inherit fields and methods from another class, promoting code reuse and organization.",
|
||||
"code": "class Employee extends Person {\n double salary;\n\n void displaySalary() {\n System.out.println(\"Salary: \" + salary);\n }\n}\n\nEmployee e = new Employee();\ne.name = \"John\";\ne.age = 35;\ne.salary = 50000.0;\ne.introduce();\ne.displaySalary();",
|
||||
"explanation": "This code demonstrates inheritance, where the Employee class inherits from the Person class. The Employee class has an additional field (salary) and a method (displaySalary). An object of the Employee class is created and methods from both the Employee and Person classes are called.",
|
||||
"result": "Output:\nHello, my name is John\nSalary: 50000.0"
|
||||
},
|
||||
{
|
||||
"title": "Encapsulation",
|
||||
"description": "Encapsulation restricts direct access to certain components of an object, promoting modularity and maintainability.",
|
||||
"code": "class BankAccount {\n private double balance;\n\n public void deposit(double amount) {\n balance += amount;\n }\n\n public void withdraw(double amount) {\n if (balance >= amount) {\n balance -= amount;\n } else {\n System.out.println(\"Insufficient funds.\");\n }\n }\n\n public double getBalance() {\n return balance;\n }\n}\n\nBankAccount account = new BankAccount();\naccount.deposit(1000.0);\naccount.withdraw(500.0);\nSystem.out.println(\"Balance: \" + account.getBalance());",
|
||||
"explanation": "This example illustrates encapsulation, where the BankAccount class's balance field is private and can only be accessed through public methods (deposit, withdraw, getBalance). This ensures that the balance cannot be directly modified from outside the class.",
|
||||
"result": "Output:\nBalance: 500.0"
|
||||
},
|
||||
{
|
||||
"title": "Polymorphism",
|
||||
"description": "Polymorphism allows objects of different classes to be treated as objects of a common super class, enhancing flexibility and integration.",
|
||||
"code": "class Animal {\n void sound() {\n System.out.println(\"Animal makes a sound\");\n }\n}\n\nclass Dog extends Animal {\n void sound() {\n System.out.println(\"Dog barks\");\n }\n}\n\nclass Cat extends Animal {\n void sound() {\n System.out.println(\"Cat meows\");\n }\n}\n\nAnimal a1 = new Dog();\nAnimal a2 = new Cat();\na1.sound(); // Dog barks\na2.sound(); // Cat meows",
|
||||
"explanation": "This code demonstrates polymorphism, where a single interface (Animal) can be used for different types (Dog and Cat). The sound method is overridden in Dog and Cat classes, and when called, the appropriate method for the actual object type is executed.",
|
||||
"result": "Output:\nDog barks\nCat meows"
|
||||
},
|
||||
{
|
||||
"title": "Interfaces",
|
||||
"description": "Interfaces in Java are abstract types that allow classes to implement multiple inheritance-like structures.",
|
||||
"code": "interface Animal {\n void makeSound();\n}\n\nclass Dog implements Animal {\n public void makeSound() {\n System.out.println(\"Bark\");\n }\n}\n\nclass Cat implements Animal {\n public void makeSound() {\n System.out.println(\"Meow\");\n }\n}\n\npublic class Main {\n public static void main(String[] args) {\n Animal dog = new Dog();\n Animal cat = new Cat();\n dog.makeSound(); // Bark\n cat.makeSound(); // Meow\n }\n}",
|
||||
"explanation": "This example demonstrates how to define an interface and implement it in multiple classes. The Animal interface has a single method, makeSound, which is implemented differently in Dog and Cat classes.",
|
||||
"result": "Output:\nBark\nMeow"
|
||||
},
|
||||
{
|
||||
"title": "Abstract Classes and Methods",
|
||||
"description": "Abstract classes and methods define a template for other classes to extend and provide concrete implementations.",
|
||||
"code": "abstract class Animal {\n abstract void makeSound();\n\n public void sleep() {\n System.out.println(\"Sleeping...\");\n }\n}\n\nclass Dog extends Animal {\n public void makeSound() {\n System.out.println(\"Bark\");\n }\n}\n\nclass Cat extends Animal {\n public void makeSound() {\n System.out.println(\"Meow\");\n }\n}\n\npublic class Main {\n public static void main(String[] args) {\n Animal dog = new Dog();\n Animal cat = new Cat();\n dog.makeSound(); // Bark\n cat.makeSound(); // Meow\n dog.sleep(); // Sleeping...\n cat.sleep(); // Sleeping...\n }\n}",
|
||||
"explanation": "This example demonstrates how to use abstract classes and methods. The Animal class is abstract and includes an abstract method makeSound that must be implemented by any subclass. It also includes a regular method sleep that can be used by all subclasses.",
|
||||
"result": "Output:\nBark\nMeow\nSleeping...\nSleeping..."
|
||||
},
|
||||
{
|
||||
"title": "Constructors",
|
||||
"description": "Constructors in Java initialize new objects and set initial values for fields.",
|
||||
"code": "class Person {\n String name;\n int age;\n\n // Default constructor\n public Person() {\n this.name = \"Unknown\";\n this.age = 0;\n }\n\n // Parameterized constructor\n public Person(String name, int age) {\n this.name = name;\n this.age = age;\n }\n}\n\npublic class Main {\n public static void main(String[] args) {\n Person p1 = new Person(); // Calls default constructor\n Person p2 = new Person(\"Alice\", 30); // Calls parameterized constructor\n System.out.println(p1.name + \" is \" + p1.age + \" years old.\");\n System.out.println(p2.name + \" is \" + p2.age + \" years old.\");\n }\n}",
|
||||
"explanation": "This code demonstrates how to define default and parameterized constructors in a class. The default constructor initializes fields to default values, while the parameterized constructor sets them based on provided arguments.",
|
||||
"result": "Output:\nUnknown is 0 years old.\nAlice is 30 years old."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "library",
|
||||
"title": "Java Standard Library",
|
||||
"description": "Explore the most commonly used Java standard library classes and their usage, including collections, I/O, and more.",
|
||||
"items": [
|
||||
{
|
||||
"title": "Collections",
|
||||
"description": "Collections in Java provide a framework for storing and manipulating groups of objects.",
|
||||
"code": "List<String> names = new ArrayList<>();\nnames.add(\"John\");\nnames.add(\"Jane\");\nnames.add(\"Bob\");\n\nSet<Integer> numbers = new HashSet<>();\nnumbers.add(1);\nnumbers.add(2);\nnumbers.add(3);\n\nMap<String, Integer> ages = new HashMap<>();\nages.put(\"John\", 30);\nages.put(\"Jane\", 25);\nages.put(\"Bob\", 35);",
|
||||
"explanation": "This example demonstrates the usage of Java collections. An ArrayList is used to store a list of names, a HashSet is used to store unique numbers, and a HashMap is used to store key-value pairs of names and ages.",
|
||||
"result": "ArrayList names contains: [\"John\", \"Jane\", \"Bob\"]\nHashSet numbers contains: [1, 2, 3]\nHashMap ages contains: {\"John\"=30, \"Jane\"=25, \"Bob\"=35}"
|
||||
},
|
||||
{
|
||||
"title": "I/O",
|
||||
"description": "Java's I/O (Input/Output) classes are used to read data from and write data to files and other input and output sources.",
|
||||
"code": "try {\n FileWriter writer = new FileWriter(\"output.txt\");\n writer.write(\"Hello, World!\");\n writer.close();\n} catch (IOException e) {\n System.out.println(\"An error occurred.\");\n e.printStackTrace();\n}\n\ntry {\n FileReader reader = new FileReader(\"input.txt\");\n // Read operations\n} catch (FileNotFoundException e) {\n System.out.println(\"An error occurred.\");\n e.printStackTrace();\n}",
|
||||
"explanation": "This code snippet shows basic file I/O operations in Java. A FileWriter is used to write text to a file, and a FileReader (commented) is used to read text from a file. Exception handling ensures that any I/O errors are caught and handled appropriately.",
|
||||
"result": "Output to file \"output.txt\" contains: Hello, World!"
|
||||
},
|
||||
{
|
||||
"title": "Networking",
|
||||
"description": "Java's networking classes allow you to communicate with other computers over a network using sockets and other protocols.",
|
||||
"code": "try {\n Socket socket = new Socket(\"example.com\", 80);\n PrintWriter out = new PrintWriter(socket.getOutputStream(), true);\n BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));\n out.println(\"GET / HTTP/1.1\\nHost: example.com\\n\\n\");\n String response = in.readLine();\n while (response != null) {\n System.out.println(response);\n response = in.readLine();\n }\n socket.close();\n} catch (IOException e) {\n System.out.println(\"An error occurred.\");\n e.printStackTrace();\n}",
|
||||
"explanation": "This example demonstrates basic networking in Java. A socket connection is established to a web server, an HTTP GET request is sent, and the server's response is read and printed line by line. Proper exception handling ensures that any networking errors are caught and handled.",
|
||||
"result": "Output:\nHTTP/1.1 200 OK\nContent-Type: text/html\n...\n(The response lines continue until the end of the response body)"
|
||||
},
|
||||
{
|
||||
"title": "Concurrency",
|
||||
"description": "Java's concurrency utilities enable parallel execution of code using threads and synchronization.",
|
||||
"code": "class MyThread extends Thread {\n public void run() {\n System.out.println(\"Thread running\");\n }\n}\n\nMyThread t1 = new MyThread();\nMyThread t2 = new MyThread();\nt1.start();\nt2.start();",
|
||||
"explanation": "This code demonstrates concurrency in Java using threads. A custom thread class is created by extending the Thread class and overriding the run method. Two threads are instantiated and started, running concurrently and printing a message.",
|
||||
"result": "Output:\nThread running\nThread running\n(The order of the output may vary)"
|
||||
},
|
||||
{
|
||||
"title": "Date and Time",
|
||||
"description": "Java's date and time API provides classes for managing dates, times, and durations.",
|
||||
"code": "import java.time.LocalDate;\nimport java.time.LocalTime;\nimport java.time.LocalDateTime;\n\nLocalDate date = LocalDate.now();\nLocalTime time = LocalTime.now();\nLocalDateTime dateTime = LocalDateTime.now();\n\nSystem.out.println(\"Date: \" + date);\nSystem.out.println(\"Time: \" + time);\nSystem.out.println(\"DateTime: \" + dateTime);",
|
||||
"explanation": "This example shows how to work with date and time using the java.time package. It retrieves and prints the current date, time, and date-time using LocalDate, LocalTime, and LocalDateTime classes, respectively.",
|
||||
"result": "Output:\nDate: 2024-06-20\nTime: 14:35:50.123\nDateTime: 2024-06-20T14:35:50.123"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "advanced",
|
||||
"title": "Advanced Java",
|
||||
"description": "Explore advanced topics in Java, including generics, lambda expressions, streams, and more.",
|
||||
"items": [
|
||||
{
|
||||
"title": "Generics",
|
||||
"description": "Generics enable types (classes and methods) to operate on objects of various types while providing compile-time type safety.",
|
||||
"code": "class Box<T> {\n private T value;\n\n public void setValue(T value) {\n this.value = value;\n }\n\n public T getValue() {\n return value;\n }\n}\n\nBox<Integer> intBox = new Box<>();\nintBox.setValue(10);\nSystem.out.println(\"Integer Value: \" + intBox.getValue());\n\nBox<String> strBox = new Box<>();\nstrBox.setValue(\"Hello\");\nSystem.out.println(\"String Value: \" + strBox.getValue());",
|
||||
"explanation": "This example demonstrates the use of generics in Java, which allow classes, interfaces, and methods to operate on types specified by the programmer. The Box class can store any type of value, and two instances of Box are created to store an Integer and a String.",
|
||||
"result": "Output:\nInteger Value: 10\nString Value: Hello"
|
||||
},
|
||||
{
|
||||
"title": "Lambda Expressions",
|
||||
"description": "Lambda expressions provide a clear and concise way to represent one method interface using an expression.",
|
||||
"code": "List<String> names = Arrays.asList(\"John\", \"Jane\", \"Bob\");\n\nnames.forEach(name -> System.out.println(name));",
|
||||
"explanation": "This code demonstrates the use of lambda expressions in Java. The forEach method of the List interface is used to iterate over the list of names and print each name. Lambda expressions provide a concise way to represent anonymous functions.",
|
||||
"result": "Output:\nJohn\nJane\nBob"
|
||||
},
|
||||
{
|
||||
"title": "Streams",
|
||||
"description": "Streams support functional-style operations on sequences of elements, such as map-reduce transformations.",
|
||||
"code": "List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);\n\nint sum = numbers.stream()\n .filter(n -> n % 2 == 0)\n .mapToInt(Integer::intValue)\n .sum();\n\nSystem.out.println(\"Sum of even numbers: \" + sum);",
|
||||
"explanation": "This example demonstrates the use of streams in Java to process a list of integers. The stream pipeline filters even numbers, converts them to integers, and calculates their sum. Streams allow for functional-style operations on collections of objects.",
|
||||
"result": "Output:\nSum of even numbers: 6"
|
||||
},
|
||||
{
|
||||
"title": "Annotations",
|
||||
"description": "Annotations provide metadata about the program, which can be used by the compiler or at runtime.",
|
||||
"code": "@Override\npublic String toString() {\n return \"Custom toString implementation\";\n}\n\n@SuppressWarnings(\"unchecked\")\npublic void myMethod() {\n List rawList = new ArrayList();\n rawList.add(\"Test\");\n}",
|
||||
"explanation": "This code demonstrates the use of annotations in Java. The @Override annotation indicates that a method is overriding a superclass method. The @SuppressWarnings annotation is used to suppress compiler warnings, in this case, unchecked type operations.",
|
||||
"result": "Output:\nMethod toString() returns: Custom toString implementation\nMethod myMethod() suppresses unchecked warnings."
|
||||
},
|
||||
{
|
||||
"title": "Reflection",
|
||||
"description": "Reflection allows inspection and manipulation of classes, methods, and fields at runtime.",
|
||||
"code": "try {\n Class<?> clazz = Class.forName(\"java.lang.String\");\n Method method = clazz.getMethod(\"substring\", int.class, int.class);\n String str = \"Hello, World!\";\n String result = (String) method.invoke(str, 7, 12);\n System.out.println(\"Result: \" + result);\n} catch (Exception e) {\n e.printStackTrace();\n}",
|
||||
"explanation": "This code demonstrates the use of reflection in Java to inspect and manipulate classes at runtime. The Class.forName method retrieves the String class, the getMethod method retrieves the substring method, and the method.invoke method calls substring on the given string.",
|
||||
"result": "Output:\nResult: World"
|
||||
},
|
||||
{
|
||||
"title": "Enums",
|
||||
"description": "Enums are special Java types used to define collections of constants.",
|
||||
"code": "enum Day {\n SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY\n}\n\npublic class Main {\n public static void main(String[] args) {\n Day today = Day.MONDAY;\n switch (today) {\n case MONDAY:\n System.out.println(\"Today is Monday\");\n break;\n case FRIDAY:\n System.out.println(\"Today is Friday\");\n break;\n default:\n System.out.println(\"Another day\");\n }\n }\n}",
|
||||
"explanation": "This example shows how to define and use an enum. The Day enum represents the days of the week, and a switch statement is used to print a message based on the current day.",
|
||||
"result": "Output:\nToday is Monday"
|
||||
},
|
||||
{
|
||||
"title": "Records",
|
||||
"description": "Records provide a compact syntax for declaring classes that are primarily used to store data.",
|
||||
"code": "public record Person(String name, int age) {}\n\npublic class Main {\n public static void main(String[] args) {\n Person person = new Person(\"John\", 25);\n System.out.println(person.name() + \" is \" + person.age() + \" years old.\");\n }\n}",
|
||||
"explanation": "This example shows how to define and use a record in Java. Records provide a compact syntax for declaring classes that are primarily used to store data and automatically generate common methods like constructors, equals, hashCode, and toString.",
|
||||
"result": "Output:\nJohn is 25 years old."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "exceptions",
|
||||
"title": "Exception Handling",
|
||||
"description": "Learn how Java handles runtime errors using try-catch blocks, the finally clause, custom exceptions, and try-with-resources.",
|
||||
"items": [
|
||||
{
|
||||
"title": "Try-Catch",
|
||||
"description": "The try-catch block lets you handle exceptions that occur during the execution of a block of code.",
|
||||
"code": "try {\n int result = 10 / 0;\n} catch (ArithmeticException e) {\n System.out.println(\"Cannot divide by zero: \" + e.getMessage());\n}",
|
||||
"explanation": "This example wraps risky code in a try block. When the division by zero throws an ArithmeticException, control jumps to the matching catch block instead of crashing the program.",
|
||||
"result": "Output:\nCannot divide by zero: / by zero"
|
||||
},
|
||||
{
|
||||
"title": "Finally",
|
||||
"description": "The finally block always runs after try/catch, whether or not an exception was thrown, making it ideal for cleanup.",
|
||||
"code": "FileWriter writer = null;\ntry {\n writer = new FileWriter(\"log.txt\");\n writer.write(\"entry\");\n} catch (IOException e) {\n System.out.println(\"Write failed.\");\n} finally {\n if (writer != null) {\n try { writer.close(); } catch (IOException ignored) {}\n }\n}",
|
||||
"explanation": "The finally block closes the file resource regardless of whether the write succeeded, preventing resource leaks even when an exception occurs.",
|
||||
"result": "Output:\n(file is always closed, even on failure)"
|
||||
},
|
||||
{
|
||||
"title": "Custom Exceptions",
|
||||
"description": "You can define your own exception types by extending Exception or RuntimeException to represent domain-specific errors.",
|
||||
"code": "class InsufficientFundsException extends Exception {\n public InsufficientFundsException(String message) {\n super(message);\n }\n}\n\nvoid withdraw(double balance, double amount) throws InsufficientFundsException {\n if (amount > balance) {\n throw new InsufficientFundsException(\"Not enough funds.\");\n }\n}",
|
||||
"explanation": "InsufficientFundsException extends Exception and carries a custom message. Callers must handle or declare it, making the failure mode explicit in the method signature.",
|
||||
"result": "Output:\nInsufficientFundsException: Not enough funds."
|
||||
},
|
||||
{
|
||||
"title": "Try-With-Resources",
|
||||
"description": "Try-with-resources automatically closes any resource that implements AutoCloseable when the block finishes.",
|
||||
"code": "try (BufferedReader reader = new BufferedReader(new FileReader(\"input.txt\"))) {\n String line = reader.readLine();\n System.out.println(line);\n} catch (IOException e) {\n System.out.println(\"Could not read file.\");\n}",
|
||||
"explanation": "The reader is declared inside the parentheses of the try statement, so Java closes it automatically when the block exits, even if an exception is thrown, without a manual finally block.",
|
||||
"result": "Output:\n(first line of input.txt, resource closed automatically)"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import raw from "./java_tutorial.json"
|
||||
|
||||
export type TopicItem = {
|
||||
title: string
|
||||
description: string
|
||||
code: string
|
||||
explanation: string
|
||||
result: string
|
||||
}
|
||||
|
||||
export type Topic = {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
items: TopicItem[]
|
||||
}
|
||||
|
||||
export const topics: Topic[] = raw.sections
|
||||
|
||||
export function getTopic(id: string | undefined): Topic | undefined {
|
||||
return topics.find((topic) => topic.id === id)
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@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%;
|
||||
|
||||
--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%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { StrictMode } from "react"
|
||||
import { createRoot } from "react-dom/client"
|
||||
import { HashRouter } from "react-router-dom"
|
||||
import App from "./App"
|
||||
import "./index.css"
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<HashRouter>
|
||||
<App />
|
||||
</HashRouter>
|
||||
</StrictMode>,
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Link } from "react-router-dom"
|
||||
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card"
|
||||
import { topics } from "@/data/topics"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<section className="py-12 md:py-24 w-full">
|
||||
<div className="container mx-auto px-4 md:px-6">
|
||||
<h1 className="text-4xl font-bold mb-4">Dot Java</h1>
|
||||
<p className="text-lg text-muted-foreground mb-12">
|
||||
A quick, code-first tour of the Java language. Pick a topic to get started.
|
||||
</p>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{topics.map((topic) => (
|
||||
<Link key={topic.id} to={`/topic/${topic.id}`}>
|
||||
<Card className="h-full transition-colors hover:bg-accent">
|
||||
<CardHeader>
|
||||
<CardTitle>{topic.title}</CardTitle>
|
||||
<CardDescription>{topic.description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="text-sm text-muted-foreground">
|
||||
{topic.items.length} topics
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Link, useParams } from "react-router-dom"
|
||||
import TopicContent from "@/components/TopicContent"
|
||||
import { getTopic } from "@/data/topics"
|
||||
|
||||
export default function Topic() {
|
||||
const { id } = useParams<{ id: string }>()
|
||||
const topic = getTopic(id)
|
||||
|
||||
if (!topic) {
|
||||
return (
|
||||
<section className="py-24 w-full text-center">
|
||||
<h1 className="text-2xl font-bold mb-4">Topic not found</h1>
|
||||
<Link to="/" className="underline">Back to all topics</Link>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
return <TopicContent topic={topic} />
|
||||
}
|
||||
Reference in New Issue
Block a user