full rework in vite

This commit is contained in:
2026-08-14 23:43:49 +02:00
parent c64f94f96b
commit a99d913420
34 changed files with 2032 additions and 6076 deletions
+39
View File
@@ -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>
)
}
+46
View File
@@ -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>
)
}
+110
View File
@@ -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">&copy; 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 &quot;Software&quot;), 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 &quot;AS IS&quot;, 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>
)
}
+113
View File
@@ -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>
);
}
+56
View File
@@ -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 }
+79
View File
@@ -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 }
+262
View File
@@ -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,
}
+122
View File
@@ -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,
}
+235
View File
@@ -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)"
}
]
}
]
}
+22
View File
@@ -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)
}
+81
View File
@@ -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';
}
}
+6
View File
@@ -0,0 +1,6 @@
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
+13
View File
@@ -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>,
)
+31
View File
@@ -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>
)
}
+19
View File
@@ -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} />
}