207 lines
7.2 KiB
Vue
207 lines
7.2 KiB
Vue
<script setup>
|
|
import RequestBuilder from '~/components/api-platform/RequestBuilder.vue'
|
|
import ResponseViewer from '~/components/api-platform/ResponseViewer.vue'
|
|
import CollectionsSidebar from '~/components/api-platform/CollectionsSidebar.vue'
|
|
import EnvironmentSelector from '~/components/api-platform/EnvironmentSelector.vue'
|
|
import SaveRequestModal from '~/components/api-platform/SaveRequestModal.vue'
|
|
import CodeGenerationModal from '~/components/api-platform/CodeGenerationModal.vue'
|
|
import ImportExportModal from '~/components/api-platform/ImportExportModal.vue'
|
|
import TestScriptsModal from '~/components/api-platform/TestScriptsModal.vue'
|
|
|
|
definePageMeta({
|
|
title: "API Platform",
|
|
middleware: ["auth"],
|
|
requiresAuth: true,
|
|
});
|
|
|
|
// Use composables for state management
|
|
const {
|
|
notifications,
|
|
dismissNotification,
|
|
showCollectionSidebar,
|
|
showSaveRequestModal
|
|
} = useApiPlatform()
|
|
|
|
// Add modal states
|
|
const showCodeGenerationModal = ref(false)
|
|
const showImportExportModal = ref(false)
|
|
const showTestScriptsModal = ref(false)
|
|
</script>
|
|
|
|
<template>
|
|
<div class="min-h-screen flex flex-col bg-gray-50 dark:bg-gray-900">
|
|
<!-- Enhanced Top Bar -->
|
|
<div class="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 shadow-sm flex-shrink-0">
|
|
<div class="px-6 py-4">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-4">
|
|
<button
|
|
@click="showCollectionSidebar = !showCollectionSidebar"
|
|
class="flex items-center justify-center p-2.5 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors group"
|
|
:title="showCollectionSidebar ? 'Hide Collections' : 'Show Collections'"
|
|
>
|
|
<Icon
|
|
name="ph:sidebar"
|
|
size="20"
|
|
class="text-gray-600 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-gray-100 transition-colors"
|
|
/>
|
|
</button>
|
|
<h2 class="text-xl font-normal text-gray-300 dark:text-white">|</h2>
|
|
<div class="flex items-center gap-3">
|
|
<h1 class="text-xl font-semibold text-gray-900 dark:text-white">API Platform</h1>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Enhanced Action Bar -->
|
|
<div class="flex items-center gap-3">
|
|
<EnvironmentSelector />
|
|
<div class="h-6 w-px bg-gray-300 dark:bg-gray-600"></div>
|
|
|
|
<!-- Test Scripts Button -->
|
|
<rs-button
|
|
variant="secondary-outline"
|
|
size="sm"
|
|
@click="showTestScriptsModal = true"
|
|
class="flex items-center gap-2"
|
|
>
|
|
<Icon name="ic:outline-quiz" size="16" />
|
|
Tests
|
|
</rs-button>
|
|
|
|
<!-- Import/Export Button -->
|
|
<rs-button
|
|
variant="secondary-outline"
|
|
size="sm"
|
|
@click="showImportExportModal = true"
|
|
class="flex items-center gap-2"
|
|
>
|
|
<Icon name="ic:outline-import-export" size="16" />
|
|
Import/Export
|
|
</rs-button>
|
|
|
|
<!-- Code Generation Button -->
|
|
<rs-button
|
|
variant="secondary-outline"
|
|
size="sm"
|
|
@click="showCodeGenerationModal = true"
|
|
class="flex items-center gap-2"
|
|
>
|
|
<Icon name="ic:outline-code" size="16" />
|
|
Code
|
|
</rs-button>
|
|
|
|
<!-- Save Button -->
|
|
<rs-button
|
|
variant="secondary-outline"
|
|
size="sm"
|
|
@click="showSaveRequestModal = true"
|
|
class="flex items-center gap-2"
|
|
>
|
|
<Icon name="ic:outline-save" size="16" />
|
|
Save
|
|
</rs-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex-1 flex">
|
|
<!-- Collections Sidebar with enhanced styling -->
|
|
<Transition
|
|
enter-active-class="transition ease-out duration-200"
|
|
enter-from-class="transform -translate-x-full"
|
|
enter-to-class="transform translate-x-0"
|
|
leave-active-class="transition ease-in duration-150"
|
|
leave-from-class="transform translate-x-0"
|
|
leave-to-class="transform -translate-x-full"
|
|
>
|
|
<CollectionsSidebar
|
|
v-if="showCollectionSidebar"
|
|
@close="showCollectionSidebar = false"
|
|
class="relative z-10 flex-shrink-0"
|
|
/>
|
|
</Transition>
|
|
|
|
<!-- Main Content Area -->
|
|
<div class="flex-1 flex flex-col min-w-0">
|
|
<!-- Request Builder -->
|
|
<div class="flex-shrink-0">
|
|
<RequestBuilder />
|
|
</div>
|
|
|
|
<!-- Response Section -->
|
|
<div class="flex-1">
|
|
<ResponseViewer />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Save Request Modal -->
|
|
<SaveRequestModal
|
|
v-if="showSaveRequestModal"
|
|
@close="showSaveRequestModal = false"
|
|
/>
|
|
|
|
<!-- Code Generation Modal -->
|
|
<CodeGenerationModal
|
|
v-if="showCodeGenerationModal"
|
|
@close="showCodeGenerationModal = false"
|
|
/>
|
|
|
|
<!-- Import/Export Modal -->
|
|
<ImportExportModal
|
|
v-if="showImportExportModal"
|
|
@close="showImportExportModal = false"
|
|
/>
|
|
|
|
<!-- Test Scripts Modal -->
|
|
<TestScriptsModal
|
|
v-if="showTestScriptsModal"
|
|
@close="showTestScriptsModal = false"
|
|
/>
|
|
|
|
<!-- Enhanced Notification System -->
|
|
<div class="fixed top-4 right-4 z-50 space-y-3 max-w-sm">
|
|
<TransitionGroup
|
|
enter-active-class="transform ease-out duration-300 transition"
|
|
enter-from-class="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
|
|
enter-to-class="translate-y-0 opacity-100 sm:translate-x-0"
|
|
leave-active-class="transition ease-in duration-100"
|
|
leave-from-class="opacity-100"
|
|
leave-to-class="opacity-0"
|
|
>
|
|
<div
|
|
v-for="notification in notifications"
|
|
:key="notification.id"
|
|
class="flex items-start gap-3 p-4 rounded-lg shadow-lg border backdrop-blur-sm transition-all duration-300 ease-in-out"
|
|
:class="{
|
|
'bg-green-50/90 border-green-200 text-green-800 dark:bg-green-900/90 dark:border-green-700 dark:text-green-200': notification.type === 'success',
|
|
'bg-red-50/90 border-red-200 text-red-800 dark:bg-red-900/90 dark:border-red-700 dark:text-red-200': notification.type === 'error',
|
|
'bg-blue-50/90 border-blue-200 text-blue-800 dark:bg-blue-900/90 dark:border-blue-700 dark:text-blue-200': notification.type === 'info',
|
|
'bg-yellow-50/90 border-yellow-200 text-yellow-800 dark:bg-yellow-900/90 dark:border-yellow-700 dark:text-yellow-200': notification.type === 'warning'
|
|
}"
|
|
>
|
|
<Icon
|
|
:name="
|
|
notification.type === 'success' ? 'ic:outline-check-circle' :
|
|
notification.type === 'error' ? 'ic:outline-error' :
|
|
notification.type === 'warning' ? 'ic:outline-warning' :
|
|
'ic:outline-info'
|
|
"
|
|
size="20"
|
|
class="flex-shrink-0 mt-0.5"
|
|
/>
|
|
<span class="text-sm font-medium flex-1 leading-relaxed">{{ notification.message }}</span>
|
|
<rs-button
|
|
variant="text"
|
|
size="sm"
|
|
@click="dismissNotification(notification.id)"
|
|
class="flex-shrink-0 opacity-70 hover:opacity-100 transition-opacity"
|
|
>
|
|
<Icon name="ic:outline-close" size="16" />
|
|
</rs-button>
|
|
</div>
|
|
</TransitionGroup>
|
|
</div>
|
|
</div>
|
|
</template> |