managerr/frontend/src/views/Settings.vue
2025-07-28 10:16:57 +02:00

449 lines
11 KiB
Vue

<template>
<div class="settings-page">
<h1>Configuration</h1>
<div v-if="successMessage" class="alert alert-success">
{{ successMessage }}
</div>
<div v-if="errorMessage" class="alert alert-danger">
{{ errorMessage }}
</div>
<div class="settings-card">
<h2>Configuration API</h2>
<p>Configurez les URLs et les clés API pour Sonarr et Radarr</p>
<form @submit.prevent="saveSettings" class="settings-form">
<div class="settings-section">
<h3>Sonarr</h3>
<div class="form-group">
<label for="sonarr-url">URL de l'API Sonarr</label>
<input
type="url"
id="sonarr-url"
v-model="settings.sonarr.url"
placeholder="http://localhost:8989/api/v3"
required
>
<small class="form-text">L'URL de base de l'API Sonarr (exemple: http://localhost:8989/api/v3)</small>
</div>
<div class="form-group">
<label for="sonarr-key">Clé API Sonarr</label>
<div class="api-key-input">
<input
:type="showSonarrKey ? 'text' : 'password'"
id="sonarr-key"
v-model="settings.sonarr.apiKey"
placeholder="Votre clé API Sonarr"
required
>
<button
type="button"
class="toggle-visibility"
@click="showSonarrKey = !showSonarrKey"
>
{{ showSonarrKey ? '🔒' : '👁️' }}
</button>
</div>
<small class="form-text">Disponible dans les paramètres de Sonarr sous "Général"</small>
</div>
<div class="form-group">
<button type="button" class="test-button" @click="testConnection('sonarr')">
Tester la connexion
</button>
<span v-if="sonarrStatus === 'success'" class="status-text success">Connexion réussie ✓</span>
<span v-if="sonarrStatus === 'error'" class="status-text error">Échec de connexion ✗</span>
</div>
</div>
<div class="settings-section">
<h3>Radarr</h3>
<div class="form-group">
<label for="radarr-url">URL de l'API Radarr</label>
<input
type="url"
id="radarr-url"
v-model="settings.radarr.url"
placeholder="http://localhost:7878/api/v3"
required
>
<small class="form-text">L'URL de base de l'API Radarr (exemple: http://localhost:7878/api/v3)</small>
</div>
<div class="form-group">
<label for="radarr-key">Clé API Radarr</label>
<div class="api-key-input">
<input
:type="showRadarrKey ? 'text' : 'password'"
id="radarr-key"
v-model="settings.radarr.apiKey"
placeholder="Votre clé API Radarr"
required
>
<button
type="button"
class="toggle-visibility"
@click="showRadarrKey = !showRadarrKey"
>
{{ showRadarrKey ? '🔒' : '👁️' }}
</button>
</div>
<small class="form-text">Disponible dans les paramètres de Radarr sous "Général"</small>
</div>
<div class="form-group">
<button type="button" class="test-button" @click="testConnection('radarr')">
Tester la connexion
</button>
<span v-if="radarrStatus === 'success'" class="status-text success">Connexion réussie ✓</span>
<span v-if="radarrStatus === 'error'" class="status-text error">Échec de connexion ✗</span>
</div>
</div>
<div class="form-actions">
<button type="submit" class="save-button" :disabled="isSaving">
{{ isSaving ? 'Enregistrement...' : 'Enregistrer les paramètres' }}
</button>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios'
const API_URL = process.env.VUE_APP_API_URL || 'http://localhost:5000/api'
export default {
name: 'SettingsPage',
data() {
return {
settings: {
sonarr: {
url: '',
apiKey: ''
},
radarr: {
url: '',
apiKey: ''
}
},
showSonarrKey: false,
showRadarrKey: false,
sonarrStatus: null,
radarrStatus: null,
successMessage: '',
errorMessage: '',
isSaving: false
}
},
mounted() {
this.loadSettings()
// Charger les paramètres du store si disponibles
if (this.$store.getters.settings) {
this.settings = JSON.parse(JSON.stringify(this.$store.getters.settings))
}
},
methods: {
async loadSettings() {
try {
const token = localStorage.getItem('token')
if (!token) {
this.$router.push('/login')
return
}
await this.$store.dispatch('loadSettings')
// Si des paramètres existent dans le store, les utiliser
const storeSettings = this.$store.getters.settings
if (storeSettings) {
if (storeSettings.sonarr) {
this.settings.sonarr = {...storeSettings.sonarr}
}
if (storeSettings.radarr) {
this.settings.radarr = {...storeSettings.radarr}
}
}
} catch (error) {
console.error('Erreur lors du chargement des paramètres:', error)
// Si c'est la première fois que l'utilisateur configure l'app, il n'y aura pas de paramètres
// Donc on ne montre pas d'erreur
}
},
async testConnection(type) {
try {
const token = localStorage.getItem('token')
if (!token) {
this.$router.push('/login')
return
}
const apiSettings = this.settings[type]
const response = await axios.post(
`${API_URL}/settings/test-connection`,
{
type,
url: apiSettings.url,
apiKey: apiSettings.apiKey
},
{
headers: {
'x-auth-token': token
}
}
)
if (response.data.success) {
this[`${type}Status`] = 'success'
setTimeout(() => {
this[`${type}Status`] = null
}, 3000)
}
} catch (error) {
console.error(`Erreur lors du test de connexion ${type}:`, error)
this[`${type}Status`] = 'error'
setTimeout(() => {
this[`${type}Status`] = null
}, 3000)
}
},
async saveSettings() {
try {
this.isSaving = true
this.successMessage = ''
this.errorMessage = ''
const token = localStorage.getItem('token')
if (!token) {
this.$router.push('/login')
return
}
// Sauvegarder les paramètres via le store
await this.$store.dispatch('saveSettings', this.settings)
this.successMessage = 'Configuration enregistrée avec succès'
setTimeout(() => {
this.successMessage = ''
}, 3000)
} catch (error) {
console.error('Erreur lors de l\'enregistrement des paramètres:', error)
this.errorMessage = 'Une erreur est survenue lors de l\'enregistrement des paramètres'
setTimeout(() => {
this.errorMessage = ''
}, 3000)
} finally {
this.isSaving = false
}
}
}
}
</script>
<style scoped>
.settings-page {
padding: 2rem;
max-width: 800px;
margin: 0 auto;
}
h1 {
margin-bottom: 2rem;
color: var(--text-color);
}
h2 {
color: var(--text-color);
margin-top: 0;
}
h3 {
color: var(--text-color);
border-bottom: 1px solid var(--border-color);
padding-bottom: 0.5rem;
margin-top: 0;
}
.settings-card {
background-color: var(--card-bg);
border-radius: 8px;
box-shadow: 0 2px 10px var(--shadow-color);
padding: 2rem;
margin-bottom: 2rem;
}
.settings-section {
margin-bottom: 2rem;
}
.form-group {
margin-bottom: 1.5rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: var(--text-color);
}
input {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--border-color);
border-radius: 4px;
font-size: 1rem;
background-color: var(--input-bg);
color: var(--input-text);
}
.api-key-input {
display: flex;
position: relative;
}
.api-key-input input {
padding-right: 3rem;
}
.toggle-visibility {
position: absolute;
right: 0;
top: 0;
height: 100%;
width: 3rem;
background: transparent;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
}
.form-text {
display: block;
margin-top: 0.5rem;
font-size: 0.85rem;
color: #6c757d;
}
.test-button {
background-color: var(--info-bg);
color: var(--info-text);
border: none;
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
font-size: 0.9rem;
transition: background-color 0.2s;
}
.test-button:hover {
filter: brightness(1.1);
}
.status-text {
margin-left: 1rem;
font-weight: 500;
animation: fadeIn 0.3s;
}
.status-text.success {
color: var(--success-text);
}
.status-text.error {
color: var(--danger-text);
}
.form-actions {
display: flex;
justify-content: flex-end;
margin-top: 2rem;
}
.save-button {
background-color: var(--button-primary-bg);
color: var(--button-primary-text);
border: none;
padding: 0.75rem 1.5rem;
border-radius: 4px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s;
}
.save-button:hover {
filter: brightness(1.1);
}
.save-button:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.alert {
padding: 1rem;
margin-bottom: 1rem;
border-radius: 4px;
animation: fadeIn 0.3s;
}
.alert-success {
background-color: var(--success-bg);
color: var(--success-text);
}
.alert-danger {
background-color: var(--danger-bg);
color: var(--danger-text);
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* Styles responsifs */
@media (max-width: 768px) {
.settings-page {
padding: 1.5rem;
}
.settings-card {
padding: 1.5rem;
}
}
@media (max-width: 576px) {
.settings-page {
padding: 1rem;
}
.settings-card {
padding: 1rem;
}
.form-actions {
justify-content: center;
}
.save-button {
width: 100%;
}
.status-text {
display: block;
margin-left: 0;
margin-top: 0.5rem;
text-align: center;
}
}
</style>