diff --git a/apps/client-ts/src/components/RootLayout/index.tsx b/apps/client-ts/src/components/RootLayout/index.tsx
index be61586d7..0354317ab 100644
--- a/apps/client-ts/src/components/RootLayout/index.tsx
+++ b/apps/client-ts/src/components/RootLayout/index.tsx
@@ -12,8 +12,6 @@ import { useStytchUser } from '@stytch/nextjs';
import useProfile from '@/hooks/useProfile';
import useProfileStore from '@/state/profileStore';
import useProjectStore from '@/state/projectStore';
-import useProjects from '@/hooks/useProjects';
-import useProjectsByUser from '@/hooks/useProjectsByUser';
const useDeviceSize = () => {
@@ -41,9 +39,9 @@ export const RootLayout = () => {
const [width, height] = useDeviceSize();
const router = useRouter()
const base = process.env.NEXT_PUBLIC_WEBAPP_DOMAIN;
- const [userId, setUserId] = useState("");
const { user } = useStytchUser();
const {data, isLoading, isError, error} = useProfile(user?.user_id!);
+
if(isLoading) {
console.log("loading profiles");
}
@@ -53,28 +51,22 @@ export const RootLayout = () => {
const { profile, setProfile } = useProfileStore();
- const { idProject, setIdProject } = useProjectStore();
- //const { data : projects, isLoading: isloadingProjects } = useProjects();
- const {data : projects, isLoading: isloadingProjects} = useProjectsByUser(userId);
- useEffect(()=>{
- if(projects && projects[0]){
- setIdProject(projects[0].id_project);
- }
- },[projects, setIdProject])
+ const { setIdProject } = useProjectStore();
- useEffect(()=> {
+ useEffect(()=> {
if(data){
- //console.log("data is "+ JSON.stringify(data));
+ //console.log("data from bundled call is "+ JSON.stringify(data));
setProfile({
id_user: data.id_user,
email: data.email!,
first_name: data.first_name,
last_name: data.last_name,
+ projects: data.projects
//id_organization: data.id_organization as string,
})
- //setUserId(data.id_user);
+ setIdProject(data.projects[0].id_project)
}
- }, [data, setProfile]);
+ }, [data, setIdProject, setProfile]);
const handlePageChange = (page: string) => {
@@ -100,7 +92,7 @@ export const RootLayout = () => {
-
+
-interface TeamSwitcherProps extends PopoverTriggerProps {}
+interface TeamSwitcherProps extends PopoverTriggerProps {
+ userId: string;
+}
interface ModalObj {
open: boolean;
status?: number; // 0 for org, 1 for project
}
-export default function TeamSwitcher({ className }: TeamSwitcherProps) {
+export default function TeamSwitcher({ className, userId }: TeamSwitcherProps) {
const [open, setOpen] = useState(false)
- const [userId, setUserId] = useState("");
-
const [showNewDialog, setShowNewDialog] = useState({
open: false,
})
- //const { data : orgs, isLoading: isloadingOrganisations } = useOrganisations();
- //const { data : projects, isLoading: isloadingProjects } = useProjects();
-
const { idProject, setIdProject } = useProjectStore();
const { profile } = useProfileStore();
- const {data : projects, isLoading: isloadingProjects} = useProjectsByUser(profile?.id_user!);
-
-
- useEffect(()=>{
- if(projects && projects[0]){
- setIdProject(projects[0].id_project);
- }
- },[projects, setIdProject])
-
- /*useEffect(() => {
- if(profile && profile.id_user){
- setUserId(profile.id_user)
- }
- }, [profile])*/
+ const projects = profile?.projects;
const handleOpenChange = (open: boolean) => {
setShowNewDialog(prevState => ({ ...prevState, open }));
@@ -139,7 +119,7 @@ export default function TeamSwitcher({ className }: TeamSwitcherProps) {
aria-label="Select a team"
className={cn("w-[250px] justify-between", className)}
>
- {projects && projects.length > 0 ? projects[0].name : isloadingProjects ? : "No projects found"}
+ {projects && projects.length > 0 ? projects[0].name : "No projects found"}
@@ -150,7 +130,7 @@ export default function TeamSwitcher({ className }: TeamSwitcherProps) {
Not found.
{
- !isloadingProjects && projects && projects.length > 0 ? projects.map((project) => (
+ projects && projects.length > 0 ? projects.map((project) => (
{
diff --git a/apps/client-ts/src/hooks/useProfile.tsx b/apps/client-ts/src/hooks/useProfile.tsx
index bac61afa2..b1f0a67d0 100644
--- a/apps/client-ts/src/hooks/useProfile.tsx
+++ b/apps/client-ts/src/hooks/useProfile.tsx
@@ -1,11 +1,12 @@
import config from '@/lib/config';
import { useQuery } from '@tanstack/react-query';
import { users as User } from 'api';
+import { projects as Project } from 'api';
const useProfile = (stytchUserId: string) => {
return useQuery({
queryKey: ['profile', stytchUserId],
- queryFn: async (): Promise => {
+ queryFn: async (): Promise => {
const response = await fetch(`${config.API_URL}/auth/users/${stytchUserId}`);
if (!response.ok) {
throw new Error('Network response was not ok');
diff --git a/apps/client-ts/src/state/profileStore.ts b/apps/client-ts/src/state/profileStore.ts
index 453366258..64ea05259 100644
--- a/apps/client-ts/src/state/profileStore.ts
+++ b/apps/client-ts/src/state/profileStore.ts
@@ -1,6 +1,8 @@
import { create } from 'zustand';
+import { projects as Project } from 'api';
-interface User {
+type User_ = User & { projects: Project[] };
+type User = {
id_user: string;
email: string;
first_name: string;
@@ -9,14 +11,14 @@ interface User {
}
interface ProfileState {
- profile: User | null;
- setProfile: (profile: User) => void;
+ profile: User_ | null;
+ setProfile: (profile: User_) => void;
}
const useProfileStore = create()((set) => ({
profile: null,
- setProfile: (profile_: User) => set({ profile: profile_ }),
+ setProfile: (profile_: User_) => set({ profile: profile_ }),
}));
export default useProfileStore;
diff --git a/packages/api/prisma/schema.prisma b/packages/api/prisma/schema.prisma
index ff8bb5b14..adde91bb6 100644
--- a/packages/api/prisma/schema.prisma
+++ b/packages/api/prisma/schema.prisma
@@ -107,10 +107,11 @@ model webhooks_reponses {
/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments
model connection_strategies {
- id_connection_strategy String @id(map: "pk_connection_strategies") @db.Uuid
+ id_connection_strategy String @id(map: "pk_connection_strategies") @db.Uuid
status Boolean
type String
- id_project String? @db.Uuid
+ id_project String? @db.Uuid
+ cs_entities cs_entities[]
}
model tcg_collections {
@@ -170,9 +171,9 @@ model connections {
expiration_timestamp DateTime? @db.Timestamp(6)
created_at DateTime @db.Timestamp(6)
connection_token String?
+ vertical String
id_project String @db.Uuid
id_linked_user String @db.Uuid
- vertical String?
linked_users linked_users @relation(fields: [id_linked_user], references: [id_linked_user], onDelete: NoAction, onUpdate: NoAction, map: "fk_11")
projects projects @relation(fields: [id_project], references: [id_project], onDelete: NoAction, onUpdate: NoAction, map: "fk_9")
@@ -413,21 +414,26 @@ model crm_users {
}
model cs_attributes {
- id_cs_attribute String @id(map: "pk_ct_attributes") @db.Uuid
+ id_cs_attribute String @id(map: "pk_ct_attributes") @db.Uuid
attribute_slug String
data_type String
- id_cs_entity String @db.Uuid
+ id_cs_entity String @db.Uuid
+ cs_entities cs_entities @relation(fields: [id_cs_entity], references: [id_cs_entity], onDelete: NoAction, onUpdate: NoAction, map: "fk_cs_entity")
+ cs_values cs_values[]
}
model cs_entities {
- id_cs_entity String @id(map: "pk_ct_entities") @db.Uuid
- id_connection_strategy String @db.Uuid
+ id_cs_entity String @id(map: "pk_ct_entities") @db.Uuid
+ id_connection_strategy String @db.Uuid
+ cs_attributes cs_attributes[]
+ connection_strategies connection_strategies @relation(fields: [id_connection_strategy], references: [id_connection_strategy], onDelete: NoAction, onUpdate: NoAction, map: "fk_cs_id")
}
model cs_values {
- id_cs_value String @id(map: "pk_ct_values") @db.Uuid
+ id_cs_value String @id(map: "pk_ct_values") @db.Uuid
value String
- id_cs_attribute String @db.Uuid
+ id_cs_attribute String @db.Uuid
+ cs_attributes cs_attributes @relation(fields: [id_cs_attribute], references: [id_cs_attribute], onDelete: NoAction, onUpdate: NoAction, map: "fk_cs_attribute")
}
/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments
diff --git a/packages/api/src/@core/auth/auth.service.ts b/packages/api/src/@core/auth/auth.service.ts
index f40607a37..d2a974d1e 100644
--- a/packages/api/src/@core/auth/auth.service.ts
+++ b/packages/api/src/@core/auth/auth.service.ts
@@ -34,12 +34,21 @@ export class AuthService {
}
async getUserByStytchId(stytchId: string) {
try {
- return await this.prisma.users.findUnique({
+ const user = await this.prisma.users.findUnique({
where: {
id_stytch: stytchId,
identification_strategy: 'b2c',
},
});
+ const projects = await this.prisma.projects.findMany({
+ where: {
+ id_user: user.id_user,
+ },
+ });
+ return {
+ ...user,
+ projects: projects,
+ };
} catch (error) {
handleServiceError(error, this.logger);
}
diff --git a/packages/api/swagger/swagger-spec.json b/packages/api/swagger/swagger-spec.json
index cb930acc2..5bccad4b7 100644
--- a/packages/api/swagger/swagger-spec.json
+++ b/packages/api/swagger/swagger-spec.json
@@ -451,6 +451,30 @@
]
}
},
+ "/projects/{userId}": {
+ "get": {
+ "operationId": "getProjectsByUser",
+ "summary": "Retrieve projects by user",
+ "parameters": [
+ {
+ "name": "userId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": ""
+ }
+ },
+ "tags": [
+ "projects"
+ ]
+ }
+ },
"/projects/create": {
"post": {
"operationId": "createProject",