diff --git a/backend/.sqlc/queries/companies.sql b/backend/.sqlc/queries/companies.sql index bbe0049e..65a8b6e7 100644 --- a/backend/.sqlc/queries/companies.sql +++ b/backend/.sqlc/queries/companies.sql @@ -46,4 +46,9 @@ ORDER BY created_at DESC; -- name: GetCompanyWithAuth :one SELECT * FROM companies -WHERE (owner_id = $1 OR $2 = 'admin') AND id = $3; \ No newline at end of file +WHERE (owner_id = $1 OR $2 = 'admin') AND id = $3; + +-- name: GetCompanyByProjectID :one +SELECT c.* FROM projects p +JOIN companies c ON c.id = p.company_id +WHERE p.id = $1; diff --git a/backend/db/companies.sql.go b/backend/db/companies.sql.go index 8dc83ba7..ee7e6b36 100644 --- a/backend/db/companies.sql.go +++ b/backend/db/companies.sql.go @@ -122,6 +122,31 @@ func (q *Queries) GetCompanyByOwnerID(ctx context.Context, ownerID string) (Comp return i, err } +const getCompanyByProjectID = `-- name: GetCompanyByProjectID :one +SELECT c.id, c.owner_id, c.name, c.description, c.date_founded, c.stages, c.website, c.wallet_address, c.linkedin_url, c.created_at, c.updated_at FROM projects p +JOIN companies c ON c.id = p.company_id +WHERE p.id = $1 +` + +func (q *Queries) GetCompanyByProjectID(ctx context.Context, id string) (Company, error) { + row := q.db.QueryRow(ctx, getCompanyByProjectID, id) + var i Company + err := row.Scan( + &i.ID, + &i.OwnerID, + &i.Name, + &i.Description, + &i.DateFounded, + &i.Stages, + &i.Website, + &i.WalletAddress, + &i.LinkedinUrl, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + const getCompanyWithAuth = `-- name: GetCompanyWithAuth :one SELECT id, owner_id, name, description, date_founded, stages, website, wallet_address, linkedin_url, created_at, updated_at FROM companies WHERE (owner_id = $1 OR $2 = 'admin') AND id = $3 diff --git a/backend/internal/v1/v1_companies/companies.go b/backend/internal/v1/v1_companies/companies.go index 6a683515..384c6f64 100644 --- a/backend/internal/v1/v1_companies/companies.go +++ b/backend/internal/v1/v1_companies/companies.go @@ -7,6 +7,7 @@ import ( "errors" "net/http" + "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/rs/zerolog/log" ) @@ -237,3 +238,30 @@ func (h *Handler) handleGetCompany(c echo.Context) error { UpdatedAt: company.UpdatedAt, }) } + +func (h *Handler) handleGetCompanyByProject(c echo.Context) error { + projectID := c.Param("id") + if _, err := uuid.Parse(projectID); err != nil { + return v1_common.Fail(c, http.StatusBadRequest, "Invalid project id", err) + } + + company, err := h.server.GetQueries().GetCompanyByProjectID(c.Request().Context(), projectID) + if err != nil { + log.Error().Err(err).Msg("failed to get company") + return v1_common.NewNotFoundError("company") + } + + return c.JSON(http.StatusOK, CompanyResponse{ + ID: company.ID, + OwnerID: company.OwnerID, + Name: company.Name, + Description: company.Description, + DateFounded: company.DateFounded, + Stages: company.Stages, + Website: company.Website, + WalletAddress: company.WalletAddress, + LinkedinURL: company.LinkedinUrl, + CreatedAt: company.CreatedAt, + UpdatedAt: company.UpdatedAt, + }) +} diff --git a/backend/internal/v1/v1_companies/routes.go b/backend/internal/v1/v1_companies/routes.go index 6284f9fe..5d860323 100644 --- a/backend/internal/v1/v1_companies/routes.go +++ b/backend/internal/v1/v1_companies/routes.go @@ -33,7 +33,7 @@ func SetupCompanyRoutes(e *echo.Group, s interfaces.CoreServer) { // Setup all the routes for getting a single company // Auth: Admins only - companies.GET("/company/:id", h.handleGetCompany, + companies.GET("/project/:id/company", h.handleGetCompanyByProject, middleware.Auth(s.GetDB(), permissions.PermViewAllProjects), ) diff --git a/frontend/src/pages/admin/_auth/_appshell/projects/$projectId.overview.tsx b/frontend/src/pages/admin/_auth/_appshell/projects/$projectId.overview.tsx index 5b3155b2..66246eba 100644 --- a/frontend/src/pages/admin/_auth/_appshell/projects/$projectId.overview.tsx +++ b/frontend/src/pages/admin/_auth/_appshell/projects/$projectId.overview.tsx @@ -2,7 +2,7 @@ import { createFileRoute, Link } from '@tanstack/react-router' import { Stack } from '@layouts' import { FiFileText, FiMessageSquare, FiDollarSign, FiTrendingUp, FiGlobe, FiLinkedin } from 'react-icons/fi' import { useEffect, useState } from 'react' -import { CompanyResponse, getCompany } from '@/services/company' +import { CompanyResponse, getCompanyByProjectId } from '@/services/company' import { TeamMember } from '@/types' import { getTeamMembers } from '@/services/teams' import { useAuth } from '@/contexts/AuthContext' @@ -199,7 +199,7 @@ function RouteComponent() { // First fetch project and company data since we need the company ID const [projectData, companyData] = await Promise.all([ getProject(accessToken, projectId), - getCompany(accessToken) + getCompanyByProjectId(accessToken, projectId) ]) if (!companyData) { diff --git a/frontend/src/services/company.ts b/frontend/src/services/company.ts index 2a9f3aaf..37d4dfbc 100644 --- a/frontend/src/services/company.ts +++ b/frontend/src/services/company.ts @@ -71,6 +71,31 @@ export async function getCompany( return json as CompanyResponse; } +export async function getCompanyByProjectId( + token: string, + projectId: string +): Promise { + const url = getApiUrl(`/project/${projectId}/company`); + const res = await fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + credentials: 'include', + }); + + if (res.status === HttpStatusCode.NOT_FOUND) { + return null; + } + + const json = await res.json(); + if (res.status !== HttpStatusCode.OK) { + throw new ApiError('Failed to get company', res.status, json); + } + return json as CompanyResponse; +} + export async function updateCompany( token: string, data: Partial @@ -85,7 +110,9 @@ export async function updateCompany( ...(data.stage && { stages: data.stage.map((s) => s.value) }), ...(data.website && { website: data.website }), ...(data.linkedin && { linkedin_url: data.linkedin }), - ...(data.wallet_address !== undefined && { wallet_address: data.wallet_address }), + ...(data.wallet_address !== undefined && { + wallet_address: data.wallet_address, + }), }; const res = await fetch(url, {