fix bug invite user
This commit is contained in:
parent
0af8a9be0b
commit
398ca613ba
|
@ -52,7 +52,7 @@ function SubSubItemComponent({ item }: { item: SubSubItem }) {
|
||||||
asChild
|
asChild
|
||||||
className={
|
className={
|
||||||
isActive
|
isActive
|
||||||
? "bg-primary/10 active text-primary"
|
? "bg-primary/40 active text-primary"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -77,7 +77,7 @@ function SubItemComponent({ item }: { item: SubItem }) {
|
||||||
asChild
|
asChild
|
||||||
className={
|
className={
|
||||||
isActive
|
isActive
|
||||||
? "bg-primary/10 active text-primary"
|
? "bg-primary/40 active text-primary"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -99,7 +99,7 @@ function SubItemComponent({ item }: { item: SubItem }) {
|
||||||
<SidebarMenuButton
|
<SidebarMenuButton
|
||||||
className={
|
className={
|
||||||
isActive
|
isActive
|
||||||
? "bg-primary/10 active text-primary"
|
? "bg-primary/40 active text-primary"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -138,7 +138,7 @@ function RecursiveNavItem({ item, index }: { item: NavItem; index: number }) {
|
||||||
asChild
|
asChild
|
||||||
className={
|
className={
|
||||||
isActive
|
isActive
|
||||||
? "bg-primary/10 active text-primary"
|
? "bg-primary/40 active text-primary"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -166,7 +166,7 @@ function RecursiveNavItem({ item, index }: { item: NavItem; index: number }) {
|
||||||
tooltip={item.title}
|
tooltip={item.title}
|
||||||
className={
|
className={
|
||||||
isActive
|
isActive
|
||||||
? "bg-primary/10 active text-primary"
|
? "bg-primary/40 active text-primary"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
@ -143,17 +143,21 @@ export default function UserManagement() {
|
||||||
user={detailUser}
|
user={detailUser}
|
||||||
open={isSheetOpen}
|
open={isSheetOpen}
|
||||||
onOpenChange={setIsSheetOpen}
|
onOpenChange={setIsSheetOpen}
|
||||||
onUserUpdate={() => refetch()}
|
onUserUpdate={() => { }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<AddUserDialog open={isAddUserOpen} onOpenChange={setIsAddUserOpen} onUserAdded={() => refetch()} />
|
<AddUserDialog
|
||||||
|
open={isAddUserOpen}
|
||||||
|
onOpenChange={setIsAddUserOpen}
|
||||||
|
onUserAdded={() => { }}
|
||||||
|
/>
|
||||||
<InviteUserDialog open={isInviteUserOpen} onOpenChange={setIsInviteUserOpen} onUserInvited={() => refetch()} />
|
<InviteUserDialog open={isInviteUserOpen} onOpenChange={setIsInviteUserOpen} onUserInvited={() => refetch()} />
|
||||||
{updateUser && (
|
{updateUser && (
|
||||||
<UserProfileSheet
|
<UserProfileSheet
|
||||||
open={isUpdateOpen}
|
open={isUpdateOpen}
|
||||||
onOpenChange={setIsUpdateOpen}
|
onOpenChange={setIsUpdateOpen}
|
||||||
userData={updateUser}
|
userData={updateUser}
|
||||||
onUserUpdated={() => refetch()}
|
onUserUpdated={() => { }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { IBanDuration, IBanUserSchema, ICredentialsBanUserSchema } from '@/src/e
|
||||||
import { ICreateUserSchema } from '@/src/entities/models/users/create-user.model';
|
import { ICreateUserSchema } from '@/src/entities/models/users/create-user.model';
|
||||||
import { IUpdateUserSchema } from '@/src/entities/models/users/update-user.model';
|
import { IUpdateUserSchema } from '@/src/entities/models/users/update-user.model';
|
||||||
import { ICredentialsInviteUserSchema } from '@/src/entities/models/users/invite-user.model';
|
import { ICredentialsInviteUserSchema } from '@/src/entities/models/users/invite-user.model';
|
||||||
|
import { ICredentialGetUserByEmailSchema } from '@/src/entities/models/users/read-user.model';
|
||||||
|
|
||||||
export async function banUser(id: string, ban_duration: IBanDuration) {
|
export async function banUser(id: string, ban_duration: IBanDuration) {
|
||||||
const instrumentationService = getInjection('IInstrumentationService');
|
const instrumentationService = getInjection('IInstrumentationService');
|
||||||
|
@ -116,9 +117,7 @@ export async function getCurrentUser() {
|
||||||
{ recordResponse: true },
|
{ recordResponse: true },
|
||||||
async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
const getCurrentUserController = getInjection(
|
const getCurrentUserController = getInjection('IGetCurrentUserController');
|
||||||
'IGetCurrentUserController'
|
|
||||||
);
|
|
||||||
return await getCurrentUserController();
|
return await getCurrentUserController();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
||||||
|
@ -182,7 +181,7 @@ export async function getUserById(id: string) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUserByEmail(email: string) {
|
export async function getUserByEmail(credential: ICredentialGetUserByEmailSchema) {
|
||||||
const instrumentationService = getInjection('IInstrumentationService');
|
const instrumentationService = getInjection('IInstrumentationService');
|
||||||
return await instrumentationService.instrumentServerAction(
|
return await instrumentationService.instrumentServerAction(
|
||||||
'getUserByEmail',
|
'getUserByEmail',
|
||||||
|
@ -192,7 +191,7 @@ export async function getUserByEmail(email: string) {
|
||||||
const getUserByEmailController = getInjection(
|
const getUserByEmailController = getInjection(
|
||||||
'IGetUserByEmailController'
|
'IGetUserByEmailController'
|
||||||
);
|
);
|
||||||
return await getUserByEmailController({ email });
|
return await getUserByEmailController({ email: credential.email });
|
||||||
|
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -7,11 +7,14 @@ import { CreateUserSchema, defaulICreateUserSchemaValues, ICreateUserSchema } fr
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { defaulIInviteUserSchemaValues, IInviteUserSchema, InviteUserSchema } from '@/src/entities/models/users/invite-user.model';
|
import { defaulIInviteUserSchemaValues, IInviteUserSchema, InviteUserSchema } from '@/src/entities/models/users/invite-user.model';
|
||||||
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
export const useAddUserDialogHandler = ({ onUserAdded, onOpenChange }: {
|
export const useAddUserDialogHandler = ({ onUserAdded, onOpenChange }: {
|
||||||
onUserAdded: () => void;
|
onUserAdded: () => void;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
|
const queryClient = useQueryClient();
|
||||||
const { createUser, isPending } = useCreateUserMutation();
|
const { createUser, isPending } = useCreateUserMutation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -38,7 +41,11 @@ export const useAddUserDialogHandler = ({ onUserAdded, onOpenChange }: {
|
||||||
|
|
||||||
await createUser(data, {
|
await createUser(data, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["users"] });
|
||||||
|
|
||||||
toast.success("User created successfully.");
|
toast.success("User created successfully.");
|
||||||
|
|
||||||
onUserAdded();
|
onUserAdded();
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
reset();
|
reset();
|
||||||
|
@ -76,6 +83,7 @@ export const useInviteUserHandler = ({ onUserInvited, onOpenChange }: {
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
|
const queryClient = useQueryClient();
|
||||||
const { inviteUser, isPending } = useInviteUserMutation();
|
const { inviteUser, isPending } = useInviteUserMutation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -95,7 +103,11 @@ export const useInviteUserHandler = ({ onUserInvited, onOpenChange }: {
|
||||||
const onSubmit = handleSubmit(async (data) => {
|
const onSubmit = handleSubmit(async (data) => {
|
||||||
await inviteUser(data, {
|
await inviteUser(data, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["users"] });
|
||||||
|
|
||||||
toast.success("Invitation sent");
|
toast.success("Invitation sent");
|
||||||
|
|
||||||
onUserInvited();
|
onUserInvited();
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
reset();
|
reset();
|
||||||
|
|
|
@ -40,7 +40,7 @@ const useUsersAction = () => {
|
||||||
|
|
||||||
const getUserByEmailQuery = (email: string) => ({
|
const getUserByEmailQuery = (email: string) => ({
|
||||||
queryKey: ["user", "email", email],
|
queryKey: ["user", "email", email],
|
||||||
queryFn: async () => await getUserByEmail(email)
|
queryFn: async () => await getUserByEmail({ email })
|
||||||
});
|
});
|
||||||
|
|
||||||
const getUserByUsernameQuery = (username: string) => ({
|
const getUserByUsernameQuery = (username: string) => ({
|
||||||
|
@ -62,7 +62,7 @@ const useUsersAction = () => {
|
||||||
// Create functions that return configured hooks
|
// Create functions that return configured hooks
|
||||||
const inviteUserMutation = useMutation({
|
const inviteUserMutation = useMutation({
|
||||||
mutationKey: ["inviteUser"],
|
mutationKey: ["inviteUser"],
|
||||||
mutationFn: async (credential: ICredentialsInviteUserSchema) => await inviteUser(credential)
|
mutationFn: async (credential: ICredentialsInviteUserSchema) => await inviteUser(credential)
|
||||||
});
|
});
|
||||||
|
|
||||||
const createUserMutation = useMutation({
|
const createUserMutation = useMutation({
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
--popover-foreground: 0 0% 10%; /* #1a1a1a */
|
--popover-foreground: 0 0% 10%; /* #1a1a1a */
|
||||||
|
|
||||||
/* Warna utama: hijau Supabase #006239 */
|
/* Warna utama: hijau Supabase #006239 */
|
||||||
--primary: 155% 100% 19%; /* #006239 */
|
--primary: 155 100% 19%; /* #006239 */
|
||||||
--primary-foreground: 0 0% 100%; /* #ffffff untuk kontras pada hijau */
|
--primary-foreground: 0 0% 100%; /* #ffffff untuk kontras pada hijau */
|
||||||
|
|
||||||
/* Sekunder: abu-abu terang untuk elemen pendukung */
|
/* Sekunder: abu-abu terang untuk elemen pendukung */
|
||||||
|
@ -41,13 +41,13 @@
|
||||||
--input: 0 0% 80%; /* #cccccc */
|
--input: 0 0% 80%; /* #cccccc */
|
||||||
|
|
||||||
/* Ring: sama dengan primary untuk fokus */
|
/* Ring: sama dengan primary untuk fokus */
|
||||||
--ring: 155% 100% 19%; /* #006239 */
|
--ring: 155 100% 19%; /* #006239 */
|
||||||
|
|
||||||
/* Radius: sudut membulat ringan */
|
/* Radius: sudut membulat ringan */
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
|
|
||||||
/* Chart: gunakan hijau Supabase dan variasi */
|
/* Chart: gunakan hijau Supabase dan variasi */
|
||||||
--chart-1: 155% 100% 19%; /* #006239 */
|
--chart-1: 155 100% 19%; /* #006239 */
|
||||||
--chart-2: 160 60% 45%; /* sedikit lebih gelap */
|
--chart-2: 160 60% 45%; /* sedikit lebih gelap */
|
||||||
--chart-3: 165 55% 40%;
|
--chart-3: 165 55% 40%;
|
||||||
--chart-4: 170 50% 35%;
|
--chart-4: 170 50% 35%;
|
||||||
|
@ -56,12 +56,12 @@
|
||||||
/* Sidebar: mirip dengan kartu di mode terang */
|
/* Sidebar: mirip dengan kartu di mode terang */
|
||||||
--sidebar-background: 0 0% 98%; /* #fafafa */
|
--sidebar-background: 0 0% 98%; /* #fafafa */
|
||||||
--sidebar-foreground: 0 0% 10%; /* #1a1a1a */
|
--sidebar-foreground: 0 0% 10%; /* #1a1a1a */
|
||||||
--sidebar-primary: 155% 100% 19%; /* #006239 */
|
--sidebar-primary: 155 100% 19%; /* #006239 */
|
||||||
--sidebar-primary-foreground: 0 0% 100%; /* #ffffff */
|
--sidebar-primary-foreground: 0 0% 100%; /* #ffffff */
|
||||||
--sidebar-accent: 0 0% 96%; /* #f5f5f5 */
|
--sidebar-accent: 0 0% 96%; /* #f5f5f5 */
|
||||||
--sidebar-accent-foreground: 0 0% 10%; /* #1a1a1a */
|
--sidebar-accent-foreground: 0 0% 10%; /* #1a1a1a */
|
||||||
--sidebar-border: 0 0% 85%; /* #d9d9d9 */
|
--sidebar-border: 0 0% 85%; /* #d9d9d9 */
|
||||||
--sidebar-ring: 155% 100% 19%; /* #006239 */
|
--sidebar-ring: 155 100% 19%; /* #006239 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
--popover-foreground: 0 0% 85%; /* #d9d9d9 */
|
--popover-foreground: 0 0% 85%; /* #d9d9d9 */
|
||||||
|
|
||||||
/* Warna utama: hijau Supabase tetap digunakan */
|
/* Warna utama: hijau Supabase tetap digunakan */
|
||||||
--primary: 155% 100% 19%; /* #006239 */
|
--primary: 155 100% 19%; /* #006239 */
|
||||||
--primary-foreground: 0 0% 100%; /* #ffffff */
|
--primary-foreground: 0 0% 100%; /* #ffffff */
|
||||||
|
|
||||||
/* Sekunder: abu-abu gelap untuk elemen pendukung */
|
/* Sekunder: abu-abu gelap untuk elemen pendukung */
|
||||||
|
@ -102,10 +102,10 @@
|
||||||
--input: 0 0% 20%; /* #333333 */
|
--input: 0 0% 20%; /* #333333 */
|
||||||
|
|
||||||
/* Ring: sama dengan primary */
|
/* Ring: sama dengan primary */
|
||||||
--ring: 155% 100% 19%; /* #006239 */
|
--ring: 155 100% 19%; /* #006239 */
|
||||||
|
|
||||||
/* Chart: sama seperti mode terang */
|
/* Chart: sama seperti mode terang */
|
||||||
--chart-1: 155% 100% 19%; /* #006239 */
|
--chart-1: 155 100% 19%; /* #006239 */
|
||||||
--chart-2: 160 60% 45%;
|
--chart-2: 160 60% 45%;
|
||||||
--chart-3: 165 55% 40%;
|
--chart-3: 165 55% 40%;
|
||||||
--chart-4: 170 50% 35%;
|
--chart-4: 170 50% 35%;
|
||||||
|
@ -114,12 +114,12 @@
|
||||||
/* Sidebar: abu-abu gelap */
|
/* Sidebar: abu-abu gelap */
|
||||||
--sidebar-background: 0 0% 15%; /* #262626 */
|
--sidebar-background: 0 0% 15%; /* #262626 */
|
||||||
--sidebar-foreground: 0 0% 85%; /* #d9d9d9 */
|
--sidebar-foreground: 0 0% 85%; /* #d9d9d9 */
|
||||||
--sidebar-primary: 155% 100% 19%; /* #006239 */
|
--sidebar-primary: 155 100% 19%; /* #006239 */
|
||||||
--sidebar-primary-foreground: 0 0% 100%; /* #ffffff */
|
--sidebar-primary-foreground: 0 0% 100%; /* #ffffff */
|
||||||
--sidebar-accent: 0 0% 20%; /* #333333 */
|
--sidebar-accent: 0 0% 20%; /* #333333 */
|
||||||
--sidebar-accent-foreground: 0 0% 85%; /* #d9d9d9 */
|
--sidebar-accent-foreground: 0 0% 85%; /* #d9d9d9 */
|
||||||
--sidebar-border: 0 0% 25%; /* #404040 */
|
--sidebar-border: 0 0% 25%; /* #404040 */
|
||||||
--sidebar-ring: 155% 100% 19%; /* #006239 */
|
--sidebar-ring: 155 100% 19%; /* #006239 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { VerifyOtpSchema } from "@/src/entities/models/auth/verify-otp.model"
|
import { IVerifyOtpSchema } from "@/src/entities/models/auth/verify-otp.model"
|
||||||
import { IUsersRepository } from "../../repositories/users.repository.interface"
|
import { IUsersRepository } from "../../repositories/users.repository.interface"
|
||||||
import { IAuthenticationService } from "../../services/authentication.service.interface"
|
import { IAuthenticationService } from "../../services/authentication.service.interface"
|
||||||
import { IInstrumentationService } from "../../services/instrumentation.service.interface"
|
import { IInstrumentationService } from "../../services/instrumentation.service.interface"
|
||||||
|
@ -12,15 +12,18 @@ export const verifyOtpUseCase = (
|
||||||
instrumentationService: IInstrumentationService,
|
instrumentationService: IInstrumentationService,
|
||||||
authenticationService: IAuthenticationService,
|
authenticationService: IAuthenticationService,
|
||||||
usersRepository: IUsersRepository
|
usersRepository: IUsersRepository
|
||||||
) => async (input: VerifyOtpSchema): Promise<void> => {
|
) => async (input: IVerifyOtpSchema): Promise<void> => {
|
||||||
return await instrumentationService.startSpan({ name: "verifyOtp Use Case", op: "function" },
|
return await instrumentationService.startSpan({ name: "verifyOtp Use Case", op: "function" },
|
||||||
async () => {
|
async () => {
|
||||||
const user = await usersRepository.getUserByEmail(input.email)
|
|
||||||
|
const user = await usersRepository.getUserByEmail({ email: input.email })
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new NotFoundError("User not found")
|
throw new NotFoundError("User not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("email = ", user.email)
|
||||||
|
|
||||||
await authenticationService.verifyOtp({
|
await authenticationService.verifyOtp({
|
||||||
email: input.email,
|
email: input.email,
|
||||||
token: input.token
|
token: input.token
|
||||||
|
|
|
@ -14,11 +14,12 @@ export const inviteUserUseCase = (
|
||||||
) => async (credential: ICredentialsInviteUserSchema): Promise<IUserSchema> => {
|
) => async (credential: ICredentialsInviteUserSchema): Promise<IUserSchema> => {
|
||||||
return await instrumentationService.startSpan({ name: "inviteUser Use Case", op: "function" },
|
return await instrumentationService.startSpan({ name: "inviteUser Use Case", op: "function" },
|
||||||
async () => {
|
async () => {
|
||||||
const existingUser = await usersRepository.getUserByEmail(credential)
|
|
||||||
|
|
||||||
if (existingUser) {
|
// const existingUser = await usersRepository.getUserByEmail(credential)
|
||||||
throw new AuthenticationError("User already exists")
|
|
||||||
}
|
// if (existingUser) {
|
||||||
|
// throw new AuthenticationError("User already exists")
|
||||||
|
// }
|
||||||
|
|
||||||
const invitedUser = await usersRepository.inviteUser(credential)
|
const invitedUser = await usersRepository.inviteUser(credential)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ export const verifyOtpController =
|
||||||
) =>
|
) =>
|
||||||
async (input: Partial<z.infer<typeof verifyOtpInputSchema>>) => {
|
async (input: Partial<z.infer<typeof verifyOtpInputSchema>>) => {
|
||||||
return await instrumentationService.startSpan({ name: "verifyOtp Controller" }, async () => {
|
return await instrumentationService.startSpan({ name: "verifyOtp Controller" }, async () => {
|
||||||
|
|
||||||
|
// console.log("input", input)
|
||||||
|
|
||||||
const { data, error: inputParseError } = verifyOtpInputSchema.safeParse(input)
|
const { data, error: inputParseError } = verifyOtpInputSchema.safeParse(input)
|
||||||
|
|
||||||
if (inputParseError) {
|
if (inputParseError) {
|
||||||
|
|
Loading…
Reference in New Issue