mirror of
https://github.com/skidoodle/budgetable.git
synced 2025-02-15 03:39:14 +01:00
formatted all
This commit is contained in:
parent
83b3a747a1
commit
c9561cb795
6 changed files with 263 additions and 228 deletions
217
src/app/page.tsx
217
src/app/page.tsx
|
@ -8,125 +8,138 @@ import { toast } from "sonner";
|
|||
import { type Budgetable, areRowsEqual } from "@/lib/utils";
|
||||
|
||||
const DEFAULT_NEW_ROW: Budgetable = {
|
||||
id: "",
|
||||
title: "",
|
||||
price: 0,
|
||||
link: "",
|
||||
note: "",
|
||||
status: "Unpaid",
|
||||
id: "",
|
||||
title: "",
|
||||
price: 0,
|
||||
link: "",
|
||||
note: "",
|
||||
status: "Unpaid",
|
||||
};
|
||||
|
||||
const ENDPOINT = "/pocketbase";
|
||||
|
||||
export default function App() {
|
||||
const [data, setData] = useState<Budgetable[]>([]);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [newRow, setNewRow] = useState<Budgetable>(DEFAULT_NEW_ROW);
|
||||
const [recentlyUpdatedRowId, setRecentlyUpdatedRowId] = useState<string | null>(null);
|
||||
const [data, setData] = useState<Budgetable[]>([]);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [newRow, setNewRow] = useState<Budgetable>(DEFAULT_NEW_ROW);
|
||||
const [recentlyUpdatedRowId, setRecentlyUpdatedRowId] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
try {
|
||||
const res = await fetch(ENDPOINT);
|
||||
if (!res.ok) throw new Error("Failed to fetch data");
|
||||
const records: Budgetable[] = await res.json();
|
||||
setData(records);
|
||||
} catch (err) {
|
||||
toast.error("Error fetching data. Please try again later.");
|
||||
console.error(err);
|
||||
}
|
||||
}, []);
|
||||
const fetchData = useCallback(async () => {
|
||||
try {
|
||||
const res = await fetch(ENDPOINT);
|
||||
if (!res.ok) throw new Error("Failed to fetch data");
|
||||
const records: Budgetable[] = await res.json();
|
||||
setData(records);
|
||||
} catch (err) {
|
||||
toast.error("Error fetching data. Please try again later.");
|
||||
console.error(err);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [fetchData]);
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [fetchData]);
|
||||
|
||||
const handleSave = useCallback(async (updatedRow: Budgetable, originalRow: Budgetable) => {
|
||||
if (areRowsEqual(updatedRow, originalRow)) return;
|
||||
const handleSave = useCallback(
|
||||
async (updatedRow: Budgetable, originalRow: Budgetable) => {
|
||||
if (areRowsEqual(updatedRow, originalRow)) return;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${ENDPOINT}/${updatedRow.id}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(updatedRow),
|
||||
});
|
||||
if (!res.ok) throw new Error("Failed to update row");
|
||||
try {
|
||||
const res = await fetch(`${ENDPOINT}/${updatedRow.id}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(updatedRow),
|
||||
});
|
||||
if (!res.ok) throw new Error("Failed to update row");
|
||||
|
||||
const updatedData = await res.json();
|
||||
setData((prev) => prev.map((row) => (row.id === updatedRow.id ? updatedData : row)));
|
||||
const updatedData = await res.json();
|
||||
setData((prev) =>
|
||||
prev.map((row) => (row.id === updatedRow.id ? updatedData : row)),
|
||||
);
|
||||
|
||||
setRecentlyUpdatedRowId(updatedRow.id);
|
||||
setTimeout(() => setRecentlyUpdatedRowId(null), 500);
|
||||
toast.success("Row updated successfully!");
|
||||
} catch (err) {
|
||||
toast.error("Error updating row. Please try again.");
|
||||
console.error(err);
|
||||
}
|
||||
}, []);
|
||||
setRecentlyUpdatedRowId(updatedRow.id);
|
||||
setTimeout(() => setRecentlyUpdatedRowId(null), 500);
|
||||
toast.success("Row updated successfully!");
|
||||
} catch (err) {
|
||||
toast.error("Error updating row. Please try again.");
|
||||
console.error(err);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleAddRow = useCallback(async () => {
|
||||
if (!newRow.title || newRow.price <= 0) {
|
||||
toast.error("Title and price are required.");
|
||||
return;
|
||||
}
|
||||
const handleAddRow = useCallback(async () => {
|
||||
if (!newRow.title || newRow.price <= 0) {
|
||||
toast.error("Title and price are required.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(ENDPOINT, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(newRow),
|
||||
});
|
||||
if (!res.ok) throw new Error("Failed to add row");
|
||||
try {
|
||||
const res = await fetch(ENDPOINT, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(newRow),
|
||||
});
|
||||
if (!res.ok) throw new Error("Failed to add row");
|
||||
|
||||
const record: Budgetable = await res.json();
|
||||
setData((prev) => [...prev, record]);
|
||||
setNewRow(DEFAULT_NEW_ROW);
|
||||
toast.success("Row added successfully!");
|
||||
} catch (err) {
|
||||
toast.error("Error adding row. Please try again.");
|
||||
console.error(err);
|
||||
}
|
||||
}, [newRow]);
|
||||
const record: Budgetable = await res.json();
|
||||
setData((prev) => [...prev, record]);
|
||||
setNewRow(DEFAULT_NEW_ROW);
|
||||
toast.success("Row added successfully!");
|
||||
} catch (err) {
|
||||
toast.error("Error adding row. Please try again.");
|
||||
console.error(err);
|
||||
}
|
||||
}, [newRow]);
|
||||
|
||||
const handleDeleteRow = useCallback(async (id: string) => {
|
||||
try {
|
||||
const res = await fetch(`${ENDPOINT}/${id}`, { method: "DELETE" });
|
||||
if (!res.ok) throw new Error("Failed to delete row");
|
||||
const handleDeleteRow = useCallback(async (id: string) => {
|
||||
try {
|
||||
const res = await fetch(`${ENDPOINT}/${id}`, { method: "DELETE" });
|
||||
if (!res.ok) throw new Error("Failed to delete row");
|
||||
|
||||
setData((prev) => prev.filter((row) => row.id !== id));
|
||||
toast.success("Row deleted successfully!");
|
||||
} catch (err) {
|
||||
toast.error("Error deleting row. Please try again.");
|
||||
console.error(err);
|
||||
}
|
||||
}, []);
|
||||
setData((prev) => prev.filter((row) => row.id !== id));
|
||||
toast.success("Row deleted successfully!");
|
||||
} catch (err) {
|
||||
toast.error("Error deleting row. Please try again.");
|
||||
console.error(err);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleStatus = useCallback(async (row: Budgetable) => {
|
||||
const updatedStatus = row.status === "Paid" ? "Unpaid" : "Paid";
|
||||
const updatedRow: Budgetable = { ...row, status: updatedStatus as "Paid" | "Unpaid" };
|
||||
await handleSave(updatedRow, row);
|
||||
}, [handleSave]);
|
||||
const toggleStatus = useCallback(
|
||||
async (row: Budgetable) => {
|
||||
const updatedStatus = row.status === "Paid" ? "Unpaid" : "Paid";
|
||||
const updatedRow: Budgetable = {
|
||||
...row,
|
||||
status: updatedStatus as "Paid" | "Unpaid",
|
||||
};
|
||||
await handleSave(updatedRow, row);
|
||||
},
|
||||
[handleSave],
|
||||
);
|
||||
|
||||
const total = data.reduce(
|
||||
(sum, item) => sum + (item.status === "Unpaid" ? item.price : 0),
|
||||
0,
|
||||
);
|
||||
const total = data.reduce(
|
||||
(sum, item) => sum + (item.status === "Unpaid" ? item.price : 0),
|
||||
0,
|
||||
);
|
||||
|
||||
return (
|
||||
<main className="container mx-auto p-4 max-w-7xl">
|
||||
<Header isEditing={isEditing} setIsEditing={setIsEditing} />
|
||||
<TotalDisplay total={total} />
|
||||
<TableWrapper
|
||||
data={data}
|
||||
isEditing={isEditing}
|
||||
setData={setData}
|
||||
newRow={newRow}
|
||||
setNewRow={setNewRow}
|
||||
recentlyUpdatedRowId={recentlyUpdatedRowId}
|
||||
handleSave={handleSave}
|
||||
handleAddRow={handleAddRow}
|
||||
handleDeleteRow={handleDeleteRow}
|
||||
toggleStatus={toggleStatus}
|
||||
/>
|
||||
</main>
|
||||
);
|
||||
return (
|
||||
<main className="container mx-auto p-4 max-w-7xl">
|
||||
<Header isEditing={isEditing} setIsEditing={setIsEditing} />
|
||||
<TotalDisplay total={total} />
|
||||
<TableWrapper
|
||||
data={data}
|
||||
isEditing={isEditing}
|
||||
setData={setData}
|
||||
newRow={newRow}
|
||||
setNewRow={setNewRow}
|
||||
recentlyUpdatedRowId={recentlyUpdatedRowId}
|
||||
handleSave={handleSave}
|
||||
handleAddRow={handleAddRow}
|
||||
handleDeleteRow={handleDeleteRow}
|
||||
toggleStatus={toggleStatus}
|
||||
/>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,84 +1,94 @@
|
|||
import pb from "@/lib/pocketbase";
|
||||
import { ResponseHelper } from "@/lib/helper";
|
||||
import { RESPONSE } from "@/lib/const";
|
||||
import { Budgetable } from "@/lib/utils";
|
||||
import type { Budgetable } from "@/lib/utils";
|
||||
|
||||
const { INTERNAL_SERVER_ERROR, MISSING_ID, FAILED_TO_DELETE_DATA, FAILED_TO_UPDATE_DATA, INVALID_DATA, SUCCESS, CREATED } = RESPONSE;
|
||||
const {
|
||||
INTERNAL_SERVER_ERROR,
|
||||
MISSING_ID,
|
||||
FAILED_TO_DELETE_DATA,
|
||||
FAILED_TO_UPDATE_DATA,
|
||||
INVALID_DATA,
|
||||
SUCCESS,
|
||||
CREATED,
|
||||
} = RESPONSE;
|
||||
const { EMAIL, PASSWORD, COLLECTION = "budgetable" } = process.env;
|
||||
|
||||
async function authenticateSuperuser(): Promise<void> {
|
||||
if (!EMAIL || !PASSWORD) {
|
||||
throw new Error("Environment variables EMAIL and PASSWORD must be set");
|
||||
}
|
||||
if (!pb.authStore.isValid) {
|
||||
await pb.collection("_superusers").authWithPassword(EMAIL, PASSWORD);
|
||||
}
|
||||
if (!EMAIL || !PASSWORD) {
|
||||
throw new Error("Environment variables EMAIL and PASSWORD must be set");
|
||||
}
|
||||
if (!pb.authStore.isValid) {
|
||||
await pb.collection("_superusers").authWithPassword(EMAIL, PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(
|
||||
_req: Request,
|
||||
context: { params: Promise<{ id: string }> }
|
||||
_req: Request,
|
||||
context: { params: Promise<{ id: string }> },
|
||||
): Promise<Response> {
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
|
||||
const id = (await context.params)?.id;
|
||||
if (!id) {
|
||||
return ResponseHelper.error(MISSING_ID);
|
||||
}
|
||||
const id = (await context.params)?.id;
|
||||
if (!id) {
|
||||
return ResponseHelper.error(MISSING_ID);
|
||||
}
|
||||
|
||||
const record: Budgetable = await pb.collection<Budgetable>(COLLECTION).getOne(id);
|
||||
return ResponseHelper.success<Budgetable>(record, CREATED.STATUS);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
return ResponseHelper.error(INTERNAL_SERVER_ERROR, error);
|
||||
}
|
||||
const record: Budgetable = await pb
|
||||
.collection<Budgetable>(COLLECTION)
|
||||
.getOne(id);
|
||||
return ResponseHelper.success<Budgetable>(record, CREATED.STATUS);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
return ResponseHelper.error(INTERNAL_SERVER_ERROR, error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(
|
||||
_req: Request,
|
||||
context: { params: Promise<{ id: string }> }
|
||||
_req: Request,
|
||||
context: { params: Promise<{ id: string }> },
|
||||
): Promise<Response> {
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
|
||||
const id = (await context.params)?.id;
|
||||
if (!id) {
|
||||
return ResponseHelper.error(MISSING_ID);
|
||||
}
|
||||
const id = (await context.params)?.id;
|
||||
if (!id) {
|
||||
return ResponseHelper.error(MISSING_ID);
|
||||
}
|
||||
|
||||
await pb.collection(COLLECTION).delete(id);
|
||||
return ResponseHelper.success(SUCCESS.MESSAGE);
|
||||
} catch (error) {
|
||||
console.error("Error deleting data:", error);
|
||||
return ResponseHelper.error(FAILED_TO_DELETE_DATA, error);
|
||||
}
|
||||
await pb.collection(COLLECTION).delete(id);
|
||||
return ResponseHelper.success(SUCCESS.MESSAGE);
|
||||
} catch (error) {
|
||||
console.error("Error deleting data:", error);
|
||||
return ResponseHelper.error(FAILED_TO_DELETE_DATA, error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(
|
||||
req: Request,
|
||||
context: { params: Promise<{ id: string }> }
|
||||
req: Request,
|
||||
context: { params: Promise<{ id: string }> },
|
||||
): Promise<Response> {
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
|
||||
const id = (await context.params)?.id;
|
||||
if (!id) {
|
||||
return ResponseHelper.error(MISSING_ID);
|
||||
}
|
||||
const id = (await context.params)?.id;
|
||||
if (!id) {
|
||||
return ResponseHelper.error(MISSING_ID);
|
||||
}
|
||||
|
||||
const body: Partial<Budgetable> = await req.json();
|
||||
if (!body.title || typeof body.price !== "number") {
|
||||
return ResponseHelper.error(INVALID_DATA);
|
||||
}
|
||||
const body: Partial<Budgetable> = await req.json();
|
||||
if (!body.title || typeof body.price !== "number") {
|
||||
return ResponseHelper.error(INVALID_DATA);
|
||||
}
|
||||
|
||||
const updatedRecord: Budgetable = await pb
|
||||
.collection<Budgetable>(COLLECTION)
|
||||
.update(id, body);
|
||||
const updatedRecord: Budgetable = await pb
|
||||
.collection<Budgetable>(COLLECTION)
|
||||
.update(id, body);
|
||||
|
||||
return ResponseHelper.success<Budgetable>(updatedRecord);
|
||||
} catch (error) {
|
||||
console.error("Error updating data:", error);
|
||||
return ResponseHelper.error(FAILED_TO_UPDATE_DATA, error);
|
||||
}
|
||||
return ResponseHelper.success<Budgetable>(updatedRecord);
|
||||
} catch (error) {
|
||||
console.error("Error updating data:", error);
|
||||
return ResponseHelper.error(FAILED_TO_UPDATE_DATA, error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
import pb from "@/lib/pocketbase";
|
||||
import { ResponseHelper } from "@/lib/helper";
|
||||
import { RESPONSE } from "@/lib/const";
|
||||
import { Budgetable } from "@/lib/utils";
|
||||
import type { Budgetable } from "@/lib/utils";
|
||||
|
||||
const { INTERNAL_SERVER_ERROR } = RESPONSE;
|
||||
const { EMAIL, PASSWORD, COLLECTION = "budgetable" } = process.env;
|
||||
|
||||
async function authenticateSuperuser(): Promise<void> {
|
||||
if (!EMAIL || !PASSWORD) {
|
||||
throw new Error("Environment variables EMAIL and PASSWORD must be set");
|
||||
}
|
||||
if (!pb.authStore.isValid) {
|
||||
await pb.collection("_superusers").authWithPassword(EMAIL, PASSWORD);
|
||||
}
|
||||
if (!EMAIL || !PASSWORD) {
|
||||
throw new Error("Environment variables EMAIL and PASSWORD must be set");
|
||||
}
|
||||
if (!pb.authStore.isValid) {
|
||||
await pb.collection("_superusers").authWithPassword(EMAIL, PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(): Promise<Response> {
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
|
||||
const records: Budgetable[] = await pb
|
||||
.collection<Budgetable>(COLLECTION)
|
||||
.getFullList();
|
||||
const records: Budgetable[] = await pb
|
||||
.collection<Budgetable>(COLLECTION)
|
||||
.getFullList();
|
||||
|
||||
return ResponseHelper.success<Budgetable[]>(records);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
return ResponseHelper.error(INTERNAL_SERVER_ERROR, error);
|
||||
}
|
||||
return ResponseHelper.success<Budgetable[]>(records);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
return ResponseHelper.error(INTERNAL_SERVER_ERROR, error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: Request): Promise<Response> {
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
try {
|
||||
await authenticateSuperuser();
|
||||
|
||||
const data: Omit<Budgetable, "id"> = await req.json();
|
||||
const data: Omit<Budgetable, "id"> = await req.json();
|
||||
|
||||
const record: Budgetable = await pb
|
||||
.collection<Budgetable>(COLLECTION)
|
||||
.create(data);
|
||||
const record: Budgetable = await pb
|
||||
.collection<Budgetable>(COLLECTION)
|
||||
.create(data);
|
||||
|
||||
return ResponseHelper.success<Budgetable>(record);
|
||||
} catch (error) {
|
||||
console.error("Error adding data:", error);
|
||||
return ResponseHelper.error(INTERNAL_SERVER_ERROR, error);
|
||||
}
|
||||
return ResponseHelper.success<Budgetable>(record);
|
||||
} catch (error) {
|
||||
console.error("Error adding data:", error);
|
||||
return ResponseHelper.error(INTERNAL_SERVER_ERROR, error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ const Header = ({ isEditing, setIsEditing }: AppHeaderProps) => (
|
|||
</Link>
|
||||
</h1>
|
||||
<Button variant="ghost" onClick={() => setIsEditing(!isEditing)} size="lg">
|
||||
<span className='text-lg'>{isEditing ? "Lock" : "Unlock"} Editing</span>
|
||||
<span className="text-lg">{isEditing ? "Lock" : "Unlock"} Editing</span>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,29 +1,41 @@
|
|||
type ResponseConstant = {
|
||||
STATUS: number;
|
||||
MESSAGE: string;
|
||||
};
|
||||
};
|
||||
|
||||
type ResponseMap = {
|
||||
type ResponseMap = {
|
||||
[key: string]: ResponseConstant;
|
||||
};
|
||||
};
|
||||
|
||||
export enum HttpStatus {
|
||||
export enum HttpStatus {
|
||||
OK = 200,
|
||||
CREATED = 201,
|
||||
BAD_REQUEST = 400,
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
}
|
||||
}
|
||||
|
||||
function createResponse(status: number, message: string): ResponseConstant {
|
||||
function createResponse(status: number, message: string): ResponseConstant {
|
||||
return { STATUS: status, MESSAGE: message };
|
||||
}
|
||||
}
|
||||
|
||||
export const RESPONSE: ResponseMap = {
|
||||
INTERNAL_SERVER_ERROR: createResponse(HttpStatus.INTERNAL_SERVER_ERROR, "Internal server error."),
|
||||
export const RESPONSE: ResponseMap = {
|
||||
INTERNAL_SERVER_ERROR: createResponse(
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
"Internal server error.",
|
||||
),
|
||||
MISSING_ID: createResponse(HttpStatus.BAD_REQUEST, "Missing ID in request."),
|
||||
FAILED_TO_DELETE_DATA: createResponse(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to delete data."),
|
||||
FAILED_TO_UPDATE_DATA: createResponse(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to update data."),
|
||||
INVALID_DATA: createResponse(HttpStatus.BAD_REQUEST, "Invalid data provided."),
|
||||
FAILED_TO_DELETE_DATA: createResponse(
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
"Failed to delete data.",
|
||||
),
|
||||
FAILED_TO_UPDATE_DATA: createResponse(
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
"Failed to update data.",
|
||||
),
|
||||
INVALID_DATA: createResponse(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Invalid data provided.",
|
||||
),
|
||||
SUCCESS: createResponse(HttpStatus.OK, "Operation completed successfully."),
|
||||
CREATED: createResponse(HttpStatus.CREATED, "Resource created successfully."),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { RESPONSE } from "@/lib/const";
|
||||
|
||||
interface ErrorResponse {
|
||||
error: {
|
||||
message: string;
|
||||
details?: unknown;
|
||||
};
|
||||
error: {
|
||||
message: string;
|
||||
details?: unknown;
|
||||
};
|
||||
}
|
||||
|
||||
type SuccessResponse<T> = T;
|
||||
|
@ -12,35 +12,35 @@ type SuccessResponse<T> = T;
|
|||
type ResponseData<T> = SuccessResponse<T> | ErrorResponse;
|
||||
|
||||
interface ResponseOptions {
|
||||
status?: number;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export class ResponseHelper<T = unknown> {
|
||||
private data: ResponseData<T>;
|
||||
private status: number;
|
||||
private data: ResponseData<T>;
|
||||
private status: number;
|
||||
|
||||
constructor(data: ResponseData<T>, options: ResponseOptions = {}) {
|
||||
this.data = data;
|
||||
this.status = options.status || 200;
|
||||
}
|
||||
constructor(data: ResponseData<T>, options: ResponseOptions = {}) {
|
||||
this.data = data;
|
||||
this.status = options.status || 200;
|
||||
}
|
||||
|
||||
static success<T>(data: T, status = RESPONSE.SUCCESS.STATUS): Response {
|
||||
return new ResponseHelper<T>(data, { status }).toResponse();
|
||||
}
|
||||
static success<T>(data: T, status = RESPONSE.SUCCESS.STATUS): Response {
|
||||
return new ResponseHelper<T>(data, { status }).toResponse();
|
||||
}
|
||||
|
||||
static error(
|
||||
constant: (typeof RESPONSE)[keyof typeof RESPONSE],
|
||||
details?: unknown
|
||||
): Response {
|
||||
return new ResponseHelper<ErrorResponse>(
|
||||
{ error: { message: constant.MESSAGE, details } },
|
||||
{ status: constant.STATUS }
|
||||
).toResponse();
|
||||
}
|
||||
static error(
|
||||
constant: (typeof RESPONSE)[keyof typeof RESPONSE],
|
||||
details?: unknown,
|
||||
): Response {
|
||||
return new ResponseHelper<ErrorResponse>(
|
||||
{ error: { message: constant.MESSAGE, details } },
|
||||
{ status: constant.STATUS },
|
||||
).toResponse();
|
||||
}
|
||||
|
||||
toResponse(): Response {
|
||||
return Response.json(this.data, {
|
||||
status: this.status,
|
||||
});
|
||||
}
|
||||
toResponse(): Response {
|
||||
return Response.json(this.data, {
|
||||
status: this.status,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue