EDMS/components/dms/dialogs/DMSAccessRequestDialog.vue
2025-05-31 12:12:00 +08:00

235 lines
7.6 KiB
Vue

<script setup>
import { ref, computed } from 'vue';
import { useDmsStore } from '~/stores/dms';
const props = defineProps({
item: {
type: Object,
required: true
},
visible: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['close', 'submit']);
// Store
const dmsStore = useDmsStore();
// Form state
const selectedAccessType = ref('view');
const accessDuration = ref('7 days');
const justification = ref('');
const isSubmitting = ref(false);
const formError = ref('');
// Access type options
const accessTypes = [
{ id: 'view', label: 'View Only', description: 'Can only view the document' },
{ id: 'download', label: 'Download', description: 'Can view and download' },
{ id: 'print', label: 'Print', description: 'Can view and print' },
{ id: 'full', label: 'Full Access', description: 'View, download and print' }
];
// Access duration options
const durationOptions = [
'7 days',
'14 days',
'30 days',
'60 days',
'90 days',
'Permanent'
];
// Computed properties
const itemTitle = computed(() => {
return props.item?.name || 'Document';
});
const itemFileName = computed(() => {
if (props.item?.type === 'file') {
return props.item.name;
}
return '';
});
// Methods
const closeDialog = () => {
// Reset form
selectedAccessType.value = 'view';
accessDuration.value = '7 days';
justification.value = '';
formError.value = '';
emit('close');
};
const submitRequest = async () => {
// Validate form
if (!selectedAccessType.value) {
formError.value = 'Please select an access type';
return;
}
if (!justification.value.trim()) {
formError.value = 'Please provide a justification for your request';
return;
}
isSubmitting.value = true;
formError.value = '';
try {
// Submit the request to the store
const request = await dmsStore.requestAccess(
props.item.id,
selectedAccessType.value,
justification.value,
accessDuration.value
);
// Emit success event
emit('submit', request);
// Close the dialog (this will also reset the form)
closeDialog();
} catch (error) {
formError.value = 'Failed to submit access request. Please try again.';
console.error('Access request error:', error);
} finally {
isSubmitting.value = false;
}
};
</script>
<template>
<rs-modal
:visible="visible"
@close="closeDialog"
title="Request Document Access"
size="md"
>
<template #body>
<div class="p-6">
<!-- Document Information Section -->
<div class="mb-6">
<div class="bg-blue-50 dark:bg-blue-900/10 rounded-lg p-4 border border-blue-200 dark:border-blue-800">
<h3 class="text-sm font-medium text-blue-900 dark:text-blue-100 mb-2">Document Information</h3>
<div class="space-y-1">
<div class="flex">
<span class="text-sm font-medium text-gray-700 dark:text-gray-300 w-12">Title:</span>
<span class="text-sm text-gray-900 dark:text-gray-100">{{ itemTitle }}</span>
</div>
<div class="flex">
<span class="text-sm font-medium text-gray-700 dark:text-gray-300 w-12">File:</span>
<span class="text-sm text-gray-600 dark:text-gray-400">{{ itemFileName }}</span>
</div>
</div>
</div>
</div>
<!-- Form error -->
<div v-if="formError" class="mb-4 p-3 bg-red-50 border border-red-200 text-red-800 rounded-md text-sm">
{{ formError }}
</div>
<!-- Access Type Section -->
<div class="mb-6">
<h3 class="text-sm font-medium text-gray-900 dark:text-gray-100 mb-3">Access Type</h3>
<div class="grid grid-cols-2 gap-3">
<div
v-for="accessType in accessTypes"
:key="accessType.id"
class="relative"
>
<label
:for="accessType.id"
class="flex items-start p-3 border rounded-lg cursor-pointer transition-colors"
:class="selectedAccessType === accessType.id
? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20'
: 'border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800'"
>
<div class="flex items-center h-5">
<input
:id="accessType.id"
v-model="selectedAccessType"
:value="accessType.id"
type="radio"
class="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500"
/>
</div>
<div class="ml-3">
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">
{{ accessType.label }}
</div>
<div class="text-xs text-gray-500 dark:text-gray-400 mt-1">
{{ accessType.description }}
</div>
</div>
</label>
</div>
</div>
</div>
<!-- Access Duration Section -->
<div class="mb-6">
<label class="block text-sm font-medium text-gray-900 dark:text-gray-100 mb-2">Access Duration</label>
<select
v-model="accessDuration"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
>
<option v-for="duration in durationOptions" :key="duration" :value="duration">
{{ duration }}
</option>
</select>
</div>
<!-- Justification Section -->
<div class="mb-6">
<label class="block text-sm font-medium text-gray-900 dark:text-gray-100 mb-2">
Justification
<span class="text-red-500">*</span>
</label>
<textarea
v-model="justification"
rows="4"
placeholder="Please explain why you need access to this document..."
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none"
></textarea>
</div>
<!-- Footer Note -->
<p class="text-xs text-gray-500 dark:text-gray-400 mb-6">
Your request will be reviewed by the document owner or administrator.
</p>
</div>
</template>
<template #footer>
<div class="flex justify-end gap-3 px-6 py-4 bg-gray-50 dark:bg-gray-800">
<rs-button
@click="closeDialog"
:disabled="isSubmitting"
variant="secondary-outline"
size="sm"
>
Cancel
</rs-button>
<rs-button
@click="submitRequest"
:disabled="isSubmitting"
variant="primary"
size="sm"
>
<svg v-if="isSubmitting" class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Submit Request
</rs-button>
</div>
</template>
</rs-modal>
</template>