165 lines
4.7 KiB
Vue
165 lines
4.7 KiB
Vue
<script setup>
|
|
import { ref } from "vue";
|
|
import { useForm } from "@inertiajs/vue3";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/Components/ui/card";
|
|
import { Button } from "@/Components/ui/button";
|
|
import { Input } from "@/Components/ui/input";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from "@/Components/ui/dialog";
|
|
import InputError from "@/Components/InputError.vue";
|
|
import { Monitor, Smartphone, LogOut, CheckCircle } from "lucide-vue-next";
|
|
import AppCard from "@/Components/app/ui/card/AppCard.vue";
|
|
|
|
defineProps({
|
|
sessions: Array,
|
|
});
|
|
|
|
const confirmingLogout = ref(false);
|
|
const passwordInput = ref(null);
|
|
|
|
const form = useForm({
|
|
password: "",
|
|
});
|
|
|
|
const confirmLogout = () => {
|
|
confirmingLogout.value = true;
|
|
|
|
setTimeout(() => passwordInput.value.focus(), 250);
|
|
};
|
|
|
|
const logoutOtherBrowserSessions = () => {
|
|
form.delete(route("other-browser-sessions.destroy"), {
|
|
preserveScroll: true,
|
|
onSuccess: () => closeModal(),
|
|
onError: () => passwordInput.value.focus(),
|
|
onFinish: () => form.reset(),
|
|
});
|
|
};
|
|
|
|
const closeModal = () => {
|
|
confirmingLogout.value = false;
|
|
|
|
form.reset();
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<AppCard
|
|
title=""
|
|
padding="none"
|
|
class="p-0! gap-0"
|
|
header-class="py-3! px-4 gap-0 text-muted-foreground"
|
|
body-class=""
|
|
>
|
|
<template #header>
|
|
<div class="flex items-center gap-2">
|
|
<LogOut size="18" />
|
|
<CardTitle>Aktivne prijave</CardTitle>
|
|
</div>
|
|
<CardDescription>
|
|
Upravljanje in izpis aktivnih prijav no drugih brskalnikih in napravah.
|
|
</CardDescription>
|
|
</template>
|
|
<!-- Other Browser Sessions -->
|
|
<div v-if="sessions && sessions.length > 0" class="space-y-4">
|
|
<div
|
|
v-for="(session, i) in sessions"
|
|
:key="i"
|
|
class="flex items-center gap-3 rounded-lg border p-3"
|
|
>
|
|
<div class="shrink-0">
|
|
<Monitor
|
|
v-if="session.agent.is_desktop"
|
|
class="h-8 w-8 text-muted-foreground"
|
|
/>
|
|
<Smartphone v-else class="h-8 w-8 text-muted-foreground" />
|
|
</div>
|
|
|
|
<div class="flex-1 min-w-0">
|
|
<div class="text-sm font-medium">
|
|
{{ session.agent.platform ? session.agent.platform : "Unknown" }} -
|
|
{{ session.agent.browser ? session.agent.browser : "Unknown" }}
|
|
</div>
|
|
<div class="text-xs text-muted-foreground mt-1">
|
|
{{ session.ip_address }}
|
|
<span
|
|
v-if="session.is_current_device"
|
|
class="inline-flex items-center ml-2 text-green-600 dark:text-green-400 font-semibold"
|
|
>
|
|
Ta naprava
|
|
</span>
|
|
<span v-else class="ml-1"> · Aktiven {{ session.last_active }} </span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div v-else class="rounded-lg border border-dashed p-8 text-center">
|
|
<Monitor class="h-12 w-12 mx-auto text-muted-foreground mb-3" />
|
|
<p class="text-sm text-muted-foreground">Najdena nobena odprta prijava.</p>
|
|
</div>
|
|
|
|
<template #footer>
|
|
<div class="flex flex-row gap-1 items-center justify-end w-full">
|
|
<Button @click="confirmLogout">
|
|
<LogOut class="h-4 w-4 mr-2" />
|
|
Log Out Other Browser Sessions
|
|
</Button>
|
|
|
|
<div
|
|
v-if="form.recentlySuccessful"
|
|
class="flex items-center gap-1.5 text-sm text-muted-foreground"
|
|
>
|
|
<CheckCircle class="h-4 w-4 text-green-600" />
|
|
<span>Done.</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</AppCard>
|
|
|
|
<!-- Log Out Other Devices Confirmation Dialog -->
|
|
<Dialog :open="confirmingLogout" @update:open="closeModal">
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>Log Out Other Browser Sessions</DialogTitle>
|
|
<DialogDescription>
|
|
Please enter your password to confirm you would like to log out of your other
|
|
browser sessions across all of your devices.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div class="py-4">
|
|
<Input
|
|
ref="passwordInput"
|
|
v-model="form.password"
|
|
type="password"
|
|
placeholder="Password"
|
|
autocomplete="current-password"
|
|
@keyup.enter="logoutOtherBrowserSessions"
|
|
/>
|
|
<InputError :message="form.errors.password" class="mt-2" />
|
|
</div>
|
|
|
|
<DialogFooter>
|
|
<Button variant="outline" @click="closeModal"> Cancel </Button>
|
|
<Button :disabled="form.processing" @click="logoutOtherBrowserSessions">
|
|
Log Out Other Browser Sessions
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</template>
|