encode state in url

This commit is contained in:
Paul Butler 2025-02-08 13:28:42 -05:00
parent ca003917e4
commit 46aa15c7ce

View File

@ -1,6 +1,7 @@
"use client" "use client"
import { useState } from "react" import { useEffect, useState } from "react"
import { useRouter, useSearchParams } from "next/navigation"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea" import { Textarea } from "@/components/ui/textarea"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
@ -11,36 +12,71 @@ import { EmojiSelector } from "@/components/emoji-selector"
import { EMOJI_LIST } from "./emoji" import { EMOJI_LIST } from "./emoji"
export default function Base64EncoderDecoder() { export default function Base64EncoderDecoder() {
const [input, setInput] = useState("") const router = useRouter()
const [emoji, setEmoji] = useState("😀") const searchParams = useSearchParams()
const [output, setOutput] = useState("")
const [isEncoding, setIsEncoding] = useState(true)
const [error, setError] = useState("")
const handleConvert = () => { // Read input state from URL parameters
try { const mode = searchParams.get("mode") || "encode"
if (isEncoding) { const inputText = searchParams.get("input") || ""
setOutput(encode(emoji, input)) const selectedEmoji = searchParams.get("emoji") || "😀"
// Store output state locally
const [outputText, setOutputText] = useState("")
const [errorText, setErrorText] = useState("")
// Update URL when input state changes
const updateURL = (updates: Record<string, string>) => {
const params = new URLSearchParams(searchParams)
Object.entries(updates).forEach(([key, value]) => {
if (value) {
params.set(key, value)
} else { } else {
setOutput(decode(input)) params.delete(key)
} }
setError("") })
router.replace(`?${params.toString()}`)
}
// Convert input whenever it changes
useEffect(() => {
try {
const isEncoding = mode === "encode"
const output = isEncoding ? encode(selectedEmoji, inputText) : decode(inputText)
setOutputText(output)
setErrorText("")
} catch (e) { } catch (e) {
setError(`Error ${isEncoding ? "encoding" : "decoding"}: Invalid input`) setOutputText("")
} setErrorText(`Error ${mode === "encode" ? "encoding" : "decoding"}: Invalid input`)
} }
}, [mode, selectedEmoji, inputText])
const handleModeToggle = (checked: boolean) => { const handleModeToggle = (checked: boolean) => {
setIsEncoding(checked) const newMode = checked ? "encode" : "decode"
setInput("") const params = {
setOutput("") mode: newMode,
setError("") input: ""
}
updateURL(newMode === "decode" ? params : { ...params, emoji: "" })
} }
const handleEmojiSelect = (emoji: string) => { const handleEmojiSelect = (emoji: string) => {
setEmoji(emoji) updateURL({ emoji })
} }
const handleInputChange = (value: string) => {
updateURL({ input: value })
}
// Handle initial URL state
useEffect(() => {
const params = new URLSearchParams(searchParams)
if (!params.has("mode")) {
updateURL({ mode: "encode" })
}
}, [])
const isEncoding = mode === "encode"
return ( return (
<div className="min-h-screen bg-gradient-to-br from-purple-400 via-pink-500 to-red-500 flex items-center justify-center p-4"> <div className="min-h-screen bg-gradient-to-br from-purple-400 via-pink-500 to-red-500 flex items-center justify-center p-4">
<Card className="w-full max-w-md"> <Card className="w-full max-w-md">
@ -58,31 +94,28 @@ export default function Base64EncoderDecoder() {
<Textarea <Textarea
placeholder={isEncoding ? "Enter text to encode" : "Paste an emoji to decode"} placeholder={isEncoding ? "Enter text to encode" : "Paste an emoji to decode"}
value={input} value={inputText}
onChange={(e) => setInput(e.target.value)} onChange={(e) => handleInputChange(e.target.value)}
className="min-h-[100px]" className="min-h-[100px]"
/> />
<EmojiSelector onEmojiSelect={handleEmojiSelect} selectedEmoji={emoji} emojiList={EMOJI_LIST} disabled={!isEncoding} /> <EmojiSelector
onEmojiSelect={handleEmojiSelect}
<Button selectedEmoji={selectedEmoji}
onClick={handleConvert} emojiList={EMOJI_LIST}
className="w-full bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700" disabled={!isEncoding}
> />
{isEncoding ? "Encode" : "Decode"}
</Button>
<Textarea <Textarea
placeholder={`${isEncoding ? "Encoded" : "Decoded"} output`} placeholder={`${isEncoding ? "Encoded" : "Decoded"} output`}
value={output} value={outputText}
readOnly readOnly
className="min-h-[100px]" className="min-h-[100px]"
/> />
{error && <div className="text-red-500 text-center">{error}</div>} {errorText && <div className="text-red-500 text-center">{errorText}</div>}
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
) )
} }