Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions src/app/api/admin/trees/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,34 @@ export async function GET() {
}

/**
* Updates and return a single tree row by id
* @returns { body: Tree[], status: number } if successful
* @returns { message: string, status: number} if error
* PUT API ROUTE: Updates a single tree by ID
*
* Updates a tree record using the provided ID and request body.
*
* Parameters:
* @param request - JSON body containing fields to update
* @param params - route parameters
* @param params.id - the ID of the tree
*
* Returns:
* - 200 with { data } on success
* - Supabase error with mapped status code
* - 500 on server error
*/
export async function PUT(req: NextRequest, { params }: IParams) {
const { id } = await params;
const body = await req.json();
try {
const message = await supabase.from("trees").update(body).eq("id", id).select().single();
const { id } = await params;
const body = await req.json();

if (message.error) {
return NextResponse.json({ error: message.error }, { status: postgrestErrorToHttpStatus(message.error) });
}
const { data, error } = await supabase.from("trees").update(body).eq("id", id).select().single();

return NextResponse.json({ message: message.data }, { status: 200 });
if (error) {
const status = postgrestErrorToHttpStatus(error);
return NextResponse.json({ error: error }, { status: status });
}
return NextResponse.json({ data: data }, { status: 200 });
} catch (error) {
return NextResponse.json({ message: "Unexpected Server Error" });
return NextResponse.json({ message: "Internal Server Error" }, { status: 500 });
}
}

Expand Down
64 changes: 30 additions & 34 deletions src/app/api/admin/trees/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { supabase } from "@/supabase-client";
import { supabase, createAuthenticatedClient } from "@/supabase-client";
import { TablesInsert } from "@/database/database.types";
import { postgrestErrorToHttpStatus } from "@/database/utils";
import { createAuthenticatedClient } from "@/supabase-client";
import { NextRequest, NextResponse } from "next/server";
/**
* Get all rows and columns of tree table as array of JS objects
* @returns { message: Tree[], status: number } if successful
* @returns { message: string, status: number } if error
* GET API ROUTE: Retrieves all trees from the database
*
* Fetches all rows and columns from the trees table, sorted by creation date ascending.
*
* Parameters: none
*
* Returns:
* - 200 with { data: Tree[] } on success
* - Supabase error with mapped status code { data: null, error: string }
* - 500 on server error { data: null, error: "Internal Server Error" }
*/
export async function GET() {
try {
Expand All @@ -15,48 +21,38 @@ export async function GET() {
return NextResponse.json({ message: error.message }, { status: postgrestErrorToHttpStatus(error) });
}
return NextResponse.json({ message: data }, { status: 200 });
Comment on lines 21 to 23
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dont forget standard attribute names here too. we want to keep them consistent across all files

} catch (error) {
return NextResponse.json({ message: "Unexpected server error" }, { status: 500 });
} catch {
return NextResponse.json({ message: "Internal Server Error" }, { status: 500 });
}
}

/**
* Admin POST API route to insert information into trees table.
* POST API ROUTE: Creates a new tree record
*
* ### Authorization
* Requires bearer token for authorization:
* "Authorization: <Bearer Token (JWT)>"
* Inserts a new row into the trees table using the JSON body from the request.
*
* ### Body
* Requires parameters from {@link TablesInsert}.
* Parameters:
* @param request - JSON body containing fields to insert, matching {@link TablesInsert<"trees">}
*
* @param request
* @returns {message: string, status: number}
* Returns:
* - 200 with { data: Tree[] } on success
* - Supabase error with mapped status code { data: null, error: string }
* - 500 on server error { data: null, error: "Internal Server Error" }
*/
export async function POST(request: NextRequest) {
try {
const authHeader = request.headers.get("Authorization") ?? "";
const bearerToken = authHeader.replace("Bearer ", "");
if (!bearerToken) {
return NextResponse.json({ message: "Bearer token is missing in headers for POST request." }, { status: 401 });
}
const authSupabase = createAuthenticatedClient(bearerToken);

const json = await request.json();
const body = json as TablesInsert<"trees">;
const response = await authSupabase.from("trees").insert(body).select();

if (response.error) {
return NextResponse.json(
{ message: response.error.message },
{ status: postgrestErrorToHttpStatus(response.error) },
);
}
return NextResponse.json({ message: response.data }, { status: 200 });
} catch (error: unknown) {
if (error instanceof Error) {
return NextResponse.json({ message: error.message }, { status: 500 });
const { data, error } = await supabase.from("trees").insert(body).select();

if (error) {
const status = postgrestErrorToHttpStatus(error);
return NextResponse.json({ error: error }, { status: status });
}
return NextResponse.json({ message: "Unexpected server error" }, { status: 500 });

return NextResponse.json({ data: data }, { status: 200 });
} catch {
return NextResponse.json({ message: "Internal Server Error" }, { status: 500 });
}
}
107 changes: 67 additions & 40 deletions src/app/api/admin/volunteers/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,73 +7,100 @@ type IParams = {
};

/**
* Example GET API route. REPLACE THIS DOCSTRING.
* @returns {message: string}
* GET API ROUTE: Fetch a single volunteer by ID
*
* Retrieves one volunteer record using the provided ID.
*
* Parameters:
* @param params - route parameters
* @param params.id - the ID of the volunteer
*
* Returns:
* - 200 with { data } on success
* - 404 if no volunteer is found
* - 500 on server error
*/
export async function GET() {
return NextResponse.json({ message: "Example volunteers slug GET message" });
export async function GET(_request: NextRequest, { params }: { params: IParams }) {
try {
const { id } = await params;

const { data, error } = await supabase.from("volunteers").select("*").eq("id", id).single();

if (error) {
const status = postgrestErrorToHttpStatus(error);
return NextResponse.json({ error: error }, { status: status });
}

if (!data) {
return NextResponse.json({ message: "Not Found" }, { status: 404 });
}

return NextResponse.json({ data: data }, { status: 200 });
} catch {
return NextResponse.json({ message: "Internal Server Error" }, { status: 500 });
}
}

/**
* PUT API ROUTE: Updates a volunteer record (what they do etc.) by their ID
*
* Takes a JSON request body that contains information neccesary to update a
* volunteers information
* PUT API ROUTE: Updates a volunteer record by ID
*
* The volunteer is identified by their ID which is found in the params attribute
* Updates a volunteer using the provided ID and request body.
*
* Parameters:
* @param request - the incoming JSON body that will be used to update the associated
* volunteer
* @param params - an object that contains parameters
* @param request - JSON body containing fields to update
* @param params - route parameters
* @param params.id - the ID of the volunteer
*
* Returns:
* - 200 with { data } on success
* - Supabase error with mapped status code
* - 500 on server error
*/
export async function PUT(request: NextRequest, { params }: { params: IParams }) {
try {
const id = params.id;
const { id } = await params;
const body = await request.json();
const message = await supabase.from("volunteers").update(body).eq("id", id).select().single();

if (message.error) {
const status = postgrestErrorToHttpStatus(message.error);
return NextResponse.json({ error: message.error }, { status });
const { data, error } = await supabase.from("volunteers").update(body).eq("id", id).select().single();

if (error) {
const status = postgrestErrorToHttpStatus(error);
return NextResponse.json({ error: error }, { status: status });
}

return NextResponse.json({ message: message.data }, { status: 200 });
} catch (error) {
return NextResponse.json({ message: "Unexpected server error" }, { status: 500 });
return NextResponse.json({ data: data }, { status: 200 });
} catch {
return NextResponse.json({ message: "Internal Server Error" }, { status: 500 });
}
}

/**
* DELETE API ROUTE: Deletes a volunteer record by their ID
*
* Removes a volunteer from the database using the provided volunteer ID.
* DELETE API ROUTE: Deletes a volunteer by ID
*
* The volunteer is identified by their ID which is found in the params attribute.
* Removes a volunteer record using the provided ID.
*
* Parameters:
* @param request - the incoming request (not used for DELETE)
* @param params - an object that contains parameters
* @param params.id - the ID of the volunteer to delete*/

* @param params - route parameters
* @param params.id - the ID of the volunteer
*
* Returns:
* - 200 with { data } containing the deleted volunteer
* - Supabase error with mapped status code
* - 500 on server error
*/
export async function DELETE(_request: NextRequest, { params }: { params: IParams }) {
try {
const id = params.id;

if (!id) {
return NextResponse.json({ message: "Volunteer ID is required" }, { status: 422 });
}
const { id } = await params;

const message = await supabase.from("volunteers").delete().eq("id", id).select().single();
const { data, error } = await supabase.from("volunteers").delete().eq("id", id).select().single();

if (message.error) {
const status = postgrestErrorToHttpStatus(message.error);
return NextResponse.json({ error: message.error }, { status });
if (error) {
const status = postgrestErrorToHttpStatus(error);
return NextResponse.json({ error: error }, { status: status });
}

return NextResponse.json({ message: message.data }, { status: 200 });
} catch (error) {
return NextResponse.json({ message: "Unexpected server error" }, { status: 500 });
return NextResponse.json({ data: data }, { status: 200 });
} catch {
return NextResponse.json({ message: "Internal Server Error" }, { status: 500 });
}
}
25 changes: 18 additions & 7 deletions src/app/api/admin/volunteers/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ import { postgrestErrorToHttpStatus } from "@/database/utils";
type Volunteer = Database["public"]["Tables"]["volunteers"]["Row"];

/**
* Admin GET API route for all volunteer information.
* @returns {message: string, status: number}
* GET API ROUTE: Retrieves all volunteers from the database
*
* Fetches all rows and columns from the volunteers table, sorted by creation date ascending.
*
* Parameters: none
*
* Returns:
* - 200 with { data: Volunteer[] } on success
* - 404 with { data: null, error: "Not Found" } if no volunteers exist
* - Supabase error with mapped status code { data: null, error: string }
* - 500 on server error { data: null, error: "Internal Server Error" }
*/
export async function GET() {
try {
Expand All @@ -17,14 +26,16 @@ export async function GET() {
.order("created_at", { ascending: true });

if (error) {
console.error("Supabase error fetching volunteers:", error.message);
return NextResponse.json({ message: error.message }, { status: postgrestErrorToHttpStatus(error) });
const status = postgrestErrorToHttpStatus(error);
return NextResponse.json({ error: error }, { status: status });
}

const normalizedData: Volunteer[] = data ?? [];
return NextResponse.json({ message: normalizedData }, { status: 200 });
if (!data || data.length === 0) {
return NextResponse.json({ data: null, error: "Not Found" }, { status: 404 });
}

NextResponse.json({ data: data }, { status: 200 });
} catch (error) {
console.error("Unexpected error in /api/admin/volunteers; ", error);
return NextResponse.json({ message: "Unexpected server error" }, { status: 500 });
}
}
Expand Down