import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { useRouter } from 'next/router' import { useCallback, useEffect, useMemo, useState } from 'react' import { toast } from 'sonner' import { ContentDiff, DiffType } from './SQLEditor.types' import { compareAsAddition, compareAsModification, compareAsNewSnippet, createSqlSnippetSkeletonV2, } from './SQLEditor.utils' import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { useProfile } from '@/lib/profile' import { useSqlEditorV2StateSnapshot } from '@/state/sql-editor-v2' export const useNewQuery = () => { const router = useRouter() const { ref } = useParams() const { profile } = useProfile() const { data: project } = useSelectedProjectQuery() const snapV2 = useSqlEditorV2StateSnapshot() const { can: canCreateSQLSnippet } = useAsyncCheckPermissions( PermissionAction.CREATE, 'user_content', { resource: { type: 'sql', owner_id: profile?.id }, subject: { id: profile?.id }, } ) const newQuery = async (sql: string, name: string, shouldRedirect: boolean = true) => { if (!ref) return console.error('Project ref is required') if (!project) return console.error('Project is required') if (!profile) return console.error('Profile is required') if (!canCreateSQLSnippet) { toast('Your queries will not be saved as you do not have sufficient permissions') return undefined } try { const snippet = createSqlSnippetSkeletonV2({ name, sql, owner_id: profile?.id, project_id: project?.id, }) snapV2.addSnippet({ projectRef: ref, snippet }) snapV2.addNeedsSaving(snippet.id) if (shouldRedirect) { router.push(`/project/${ref}/sql/${snippet.id}`) return undefined } else { return snippet.id } } catch (error: any) { toast.error(`Failed to create new query: ${error.message}`) return undefined } } return { newQuery } } export function useSqlEditorDiff() { const [sourceSqlDiff, setSourceSqlDiff] = useState() const [selectedDiffType, setSelectedDiffType] = useState() const [isAcceptDiffLoading, setIsAcceptDiffLoading] = useState(false) const isDiffOpen = !!sourceSqlDiff const defaultSqlDiff = useMemo(() => { if (!sourceSqlDiff) { return { original: '', modified: '' } } switch (selectedDiffType) { case DiffType.Modification: return compareAsModification(sourceSqlDiff) case DiffType.Addition: return compareAsAddition(sourceSqlDiff) case DiffType.NewSnippet: return compareAsNewSnippet(sourceSqlDiff) default: return { original: '', modified: '' } } }, [selectedDiffType, sourceSqlDiff]) const closeDiff = useCallback(() => { setSourceSqlDiff(undefined) setSelectedDiffType(undefined) }, []) return { sourceSqlDiff, setSourceSqlDiff, selectedDiffType, setSelectedDiffType, isAcceptDiffLoading, setIsAcceptDiffLoading, isDiffOpen, defaultSqlDiff, closeDiff, } } interface PromptState { isOpen: boolean selection: string beforeSelection: string afterSelection: string startLineNumber: number endLineNumber: number } const initialPromptState: PromptState = { isOpen: false, selection: '', beforeSelection: '', afterSelection: '', startLineNumber: 0, endLineNumber: 0, } export function useSqlEditorPrompt() { const [promptState, setPromptState] = useState(initialPromptState) const [promptInput, setPromptInput] = useState('') useEffect(() => { if (!promptState.isOpen) { setPromptInput('') } }, [promptState.isOpen]) const resetPrompt = () => { setPromptState(initialPromptState) setPromptInput('') } return { promptState, setPromptState, promptInput, setPromptInput, resetPrompt, } } export default useNewQuery