feat: implement dynamic routing for editor to support persistent letter editing via public_id

This commit is contained in:
Your Name
2026-04-12 04:55:21 +05:30
parent ab080d4266
commit 5ca4be0dde
3 changed files with 19 additions and 10 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ export default function App() {
} }
/> />
<Route <Route
path={ROUTES.WRITE} path={ROUTES.WRITE()}
element={ element={
<ProtectedRoute> <ProtectedRoute>
<Editor /> <Editor />
+2 -1
View File
@@ -5,6 +5,7 @@ export const ROUTES = {
ACTIVATE: "/activate/:uidb64/:token", ACTIVATE: "/activate/:uidb64/:token",
LOGIN: "/login", LOGIN: "/login",
DRAWER: "/drawer", DRAWER: "/drawer",
WRITE: "/quill", WRITE: (public_id?: string) =>
`/quill/${public_id ? public_id : ":public_id?"}`,
READ: "/read", READ: "/read",
}; };
+16 -8
View File
@@ -6,6 +6,7 @@ import {
} from "@phosphor-icons/react"; } from "@phosphor-icons/react";
import type { FabricObject } from "fabric"; import type { FabricObject } from "fabric";
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { api } from "../api/apiClient"; import { api } from "../api/apiClient";
import { import {
type CanvasTools, type CanvasTools,
@@ -13,11 +14,14 @@ import {
} from "../components/ui/ComposeCanvas"; } from "../components/ui/ComposeCanvas";
import DateDisplay from "../components/ui/DateDisplay"; import DateDisplay from "../components/ui/DateDisplay";
import { endpoints } from "../config/endpoints"; import { endpoints } from "../config/endpoints";
import { ROUTES } from "../config/routes";
import { useKeyStore } from "../store/useKeyStore"; import { useKeyStore } from "../store/useKeyStore";
import { CryptoUtils } from "../utils/crypto"; import { CryptoUtils } from "../utils/crypto";
export default function Editor() { export default function Editor() {
const [_letterId] = useState(() => crypto.randomUUID()); const { public_id } = useParams();
const letterIdRef = useRef<string>(public_id ?? null);
const navigate = useNavigate();
const [isSealing, setIsSealing] = useState(false); const [isSealing, setIsSealing] = useState(false);
const [isSaveSuccess, setIsSaveSuccess] = useState(false); const [isSaveSuccess, setIsSaveSuccess] = useState(false);
@@ -35,6 +39,10 @@ export default function Editor() {
}; };
async function handleSeal(): Promise<void> { async function handleSeal(): Promise<void> {
if (!public_id) {
letterIdRef.current = crypto.randomUUID();
navigate(ROUTES.WRITE(letterIdRef.current), { replace: true });
}
if (isSealing) return; if (isSealing) return;
setIsSealing(true); setIsSealing(true);
const cryptoUtils = new CryptoUtils(); const cryptoUtils = new CryptoUtils();
@@ -85,7 +93,7 @@ export default function Editor() {
} }
*/ */
const formData = new FormData(); const formData = new FormData();
formData.append("public_id", _letterId); formData.append("public_id", letterIdRef.current);
formData.append("type", "SENT"); formData.append("type", "SENT");
formData.append("status", "SEALED"); formData.append("status", "SEALED");
formData.append("encrypted_content", encrypted_letter.encrypted_content); formData.append("encrypted_content", encrypted_letter.encrypted_content);
@@ -96,7 +104,7 @@ export default function Editor() {
}); });
try { try {
await api.post(endpoints.LETTERS, formData); await api.put(`${endpoints.LETTERS}${letterIdRef.current}/`, formData);
setIsSaveSuccess(true); setIsSaveSuccess(true);
setTimeout(() => { setTimeout(() => {
setIsSaveSuccess(false); setIsSaveSuccess(false);
@@ -111,13 +119,13 @@ export default function Editor() {
return ( return (
<section className="flex-1 overflow-y-auto scrollbar-hide px-2 py-12 bg-base-300"> <section className="flex-1 overflow-y-auto scrollbar-hide px-2 py-12 bg-base-300">
{isSaveSuccess && ( {isSaveSuccess && (
<div className="modal bg-transparent modal-open"> <div className="modal modal-open bg-transparent backdrop-blur-md transition-all duration-300 ease-in-out">
<div className="modal-box bg-base-100"> <div className="modal-box bg-transparent">
<div className="alert alert-success"> <div className="alert alert-success">
<DownloadSimpleIcon size={18} weight="bold" /> <DownloadSimpleIcon size={18} weight="bold" />
<h3 className="font-bold text-lg">Letter saved successfully!</h3> <h3 className="font-bold text-lg">Your letter is sealed!</h3>
</div> </div>
<div className="modal-action"> {/* <div className="modal-action">
<button <button
type="button" type="button"
className="btn btn-primary" className="btn btn-primary"
@@ -125,7 +133,7 @@ export default function Editor() {
> >
Close Close
</button> </button>
</div> </div> */}
</div> </div>
</div> </div>
)} )}