| import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
| import { useTranslation } from 'react-i18next';
|
| import { graphqlRequest } from '@/gql/graphql';
|
| import { toast } from 'sonner';
|
| import i18n from '@/lib/i18n';
|
| import { useErrorHandler } from '@/hooks/use-error-handler';
|
| import { Project, ProjectConnection, CreateProjectInput, UpdateProjectInput, projectConnectionSchema, projectSchema } from './schema';
|
|
|
|
|
| const PROJECTS_QUERY = `
|
| query GetProjects($first: Int, $after: Cursor, $orderBy: ProjectOrder, $where: ProjectWhereInput) {
|
| projects(first: $first, after: $after, orderBy: $orderBy, where: $where) {
|
| edges {
|
| node {
|
| id
|
| createdAt
|
| updatedAt
|
| name
|
| description
|
| status
|
| }
|
| cursor
|
| }
|
| pageInfo {
|
| hasNextPage
|
| hasPreviousPage
|
| startCursor
|
| endCursor
|
| }
|
| totalCount
|
| }
|
| }
|
| `;
|
|
|
| const CREATE_PROJECT_MUTATION = `
|
| mutation CreateProject($input: CreateProjectInput!) {
|
| createProject(input: $input) {
|
| id
|
| name
|
| description
|
| status
|
| createdAt
|
| updatedAt
|
| }
|
| }
|
| `;
|
|
|
| const UPDATE_PROJECT_MUTATION = `
|
| mutation UpdateProject($id: ID!, $input: UpdateProjectInput!) {
|
| updateProject(id: $id, input: $input) {
|
| id
|
| name
|
| description
|
| status
|
| createdAt
|
| updatedAt
|
| }
|
| }
|
| `;
|
|
|
| const UPDATE_PROJECT_STATUS_MUTATION = `
|
| mutation UpdateProjectStatus($id: ID!, $status: ProjectStatus!) {
|
| updateProjectStatus(id: $id, status: $status) {
|
| id
|
| name
|
| description
|
| status
|
| createdAt
|
| updatedAt
|
| }
|
| }
|
| `;
|
|
|
| const MY_PROJECTS_QUERY = `
|
| query MyProjects {
|
| myProjects {
|
| id
|
| name
|
| description
|
| status
|
| createdAt
|
| updatedAt
|
| }
|
| }
|
| `;
|
|
|
|
|
| export function useProjects(
|
| variables: {
|
| first?: number;
|
| after?: string;
|
| orderBy?: { field: 'CREATED_AT'; direction: 'ASC' | 'DESC' };
|
| where?: any;
|
| } = {}
|
| ) {
|
| const { handleError } = useErrorHandler();
|
| const { t } = useTranslation();
|
|
|
| const queryVariables = {
|
| ...variables,
|
| orderBy: variables.orderBy || { field: 'CREATED_AT', direction: 'DESC' },
|
| };
|
|
|
| return useQuery({
|
| queryKey: ['projects', queryVariables],
|
| queryFn: async () => {
|
| try {
|
| const data = await graphqlRequest<{ projects: ProjectConnection }>(PROJECTS_QUERY, queryVariables);
|
| return projectConnectionSchema.parse(data?.projects);
|
| } catch (error) {
|
| handleError(error, t('projects.errors.loadProjectsFailed'));
|
| throw error;
|
| }
|
| },
|
| });
|
| }
|
|
|
| export function useProject(id: string) {
|
| const { handleError } = useErrorHandler();
|
| const { t } = useTranslation();
|
|
|
| return useQuery({
|
| queryKey: ['project', id],
|
| queryFn: async () => {
|
| try {
|
| const data = await graphqlRequest<{ projects: ProjectConnection }>(PROJECTS_QUERY, { where: { id } });
|
| const project = data.projects.edges[0]?.node;
|
| if (!project) {
|
| throw new Error('Project not found');
|
| }
|
| return projectSchema.parse(project);
|
| } catch (error) {
|
| handleError(error, t('projects.errors.loadProjectDetailFailed'));
|
| throw error;
|
| }
|
| },
|
| enabled: !!id,
|
| });
|
| }
|
|
|
| export function useMyProjects() {
|
| const { handleError } = useErrorHandler();
|
| const { t } = useTranslation();
|
|
|
| return useQuery({
|
| queryKey: ['myProjects'],
|
| queryFn: async () => {
|
| try {
|
| const data = await graphqlRequest<{ myProjects: Project[] }>(MY_PROJECTS_QUERY);
|
|
|
| if (!data || !data.myProjects) {
|
| return [];
|
| }
|
|
|
|
|
| const projects = data.myProjects.map((project) => projectSchema.parse(project));
|
|
|
| return projects;
|
| } catch (error) {
|
| handleError(error, t('projects.errors.loadMyProjectsFailed'));
|
| return [];
|
| }
|
| },
|
| });
|
| }
|
|
|
|
|
| export function useCreateProject() {
|
| const queryClient = useQueryClient();
|
| const { handleError } = useErrorHandler();
|
|
|
| return useMutation({
|
| mutationFn: async (input: CreateProjectInput) => {
|
| try {
|
| const data = await graphqlRequest<{ createProject: Project }>(CREATE_PROJECT_MUTATION, { input });
|
| return projectSchema.parse(data.createProject);
|
| } catch (error) {
|
| handleError(error, i18n.t('projects.errors.createProjectFailed'));
|
| throw error;
|
| }
|
| },
|
| onSuccess: () => {
|
| queryClient.invalidateQueries({ queryKey: ['projects'] });
|
| queryClient.invalidateQueries({ queryKey: ['myProjects'] });
|
| toast.success(i18n.t('common.success.projectCreated'));
|
| },
|
| });
|
| }
|
|
|
| export function useUpdateProject() {
|
| const queryClient = useQueryClient();
|
| const { handleError } = useErrorHandler();
|
|
|
| return useMutation({
|
| mutationFn: async ({ id, input }: { id: string; input: UpdateProjectInput }) => {
|
| try {
|
| const data = await graphqlRequest<{ updateProject: Project }>(UPDATE_PROJECT_MUTATION, { id, input });
|
| return projectSchema.parse(data.updateProject);
|
| } catch (error) {
|
| handleError(error, i18n.t('projects.errors.updateProjectFailed'));
|
| throw error;
|
| }
|
| },
|
| onSuccess: () => {
|
| queryClient.invalidateQueries({ queryKey: ['projects'] });
|
| queryClient.invalidateQueries({ queryKey: ['project'] });
|
| queryClient.invalidateQueries({ queryKey: ['myProjects'] });
|
| toast.success(i18n.t('common.success.projectUpdated'));
|
| },
|
| });
|
| }
|
|
|
| export function useArchiveProject() {
|
| const queryClient = useQueryClient();
|
| const { handleError } = useErrorHandler();
|
|
|
| return useMutation({
|
| mutationFn: async (id: string) => {
|
| try {
|
| const data = await graphqlRequest<{ updateProjectStatus: Project }>(UPDATE_PROJECT_STATUS_MUTATION, {
|
| id,
|
| status: 'archived',
|
| });
|
| return projectSchema.parse(data.updateProjectStatus);
|
| } catch (error) {
|
| handleError(error, i18n.t('projects.errors.archiveProjectFailed'));
|
| throw error;
|
| }
|
| },
|
| onSuccess: () => {
|
| queryClient.invalidateQueries({ queryKey: ['projects'] });
|
| queryClient.invalidateQueries({ queryKey: ['project'] });
|
| queryClient.invalidateQueries({ queryKey: ['myProjects'] });
|
| toast.success(i18n.t('common.success.projectArchived'));
|
| },
|
| });
|
| }
|
|
|
| export function useActivateProject() {
|
| const queryClient = useQueryClient();
|
| const { handleError } = useErrorHandler();
|
|
|
| return useMutation({
|
| mutationFn: async (id: string) => {
|
| try {
|
| const data = await graphqlRequest<{ updateProjectStatus: Project }>(UPDATE_PROJECT_STATUS_MUTATION, {
|
| id,
|
| status: 'active',
|
| });
|
| return projectSchema.parse(data.updateProjectStatus);
|
| } catch (error) {
|
| handleError(error, i18n.t('projects.errors.activateProjectFailed'));
|
| throw error;
|
| }
|
| },
|
| onSuccess: () => {
|
| queryClient.invalidateQueries({ queryKey: ['projects'] });
|
| queryClient.invalidateQueries({ queryKey: ['project'] });
|
| queryClient.invalidateQueries({ queryKey: ['myProjects'] });
|
| toast.success(i18n.t('common.success.projectActivated'));
|
| },
|
| });
|
| }
|
|
|