105 lines
4.3 KiB
Vue
105 lines
4.3 KiB
Vue
<script setup lang="ts">
|
|
import { useRequestStore } from '../stores/requestStore';
|
|
import MethodBadge from './MethodBadge.vue';
|
|
import { Zap, Settings, Trash, Trash2, Plus } from 'lucide-vue-next';
|
|
|
|
const emit = defineEmits(['open-settings']);
|
|
const store = useRequestStore();
|
|
|
|
const getStatusColor = (code?: number) => {
|
|
if (!code) return 'text-slate-500 bg-slate-800/50';
|
|
if (code >= 200 && code < 300) return 'text-emerald-400 bg-emerald-500/10';
|
|
if (code >= 300 && code < 400) return 'text-blue-400 bg-blue-500/10';
|
|
if (code >= 400 && code < 500) return 'text-amber-400 bg-amber-500/10';
|
|
if (code >= 500) return 'text-rose-400 bg-rose-500/10';
|
|
return 'text-slate-400 bg-slate-500/10';
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<aside class="w-64 flex-shrink-0 border-r border-slate-800 flex flex-col bg-slate-950">
|
|
<!-- Header -->
|
|
<div class="h-14 flex items-center justify-between px-4 border-b border-slate-800">
|
|
<div class="flex items-center gap-2">
|
|
<div class="bg-indigo-500/20 p-1.5 rounded-lg">
|
|
<Zap class="w-5 h-5 text-indigo-400" />
|
|
</div>
|
|
<span class="font-bold text-slate-100 tracking-tight">LiteRequest</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="flex p-2 gap-2 border-b border-slate-800/50">
|
|
<button
|
|
@click="store.resetActiveRequest()"
|
|
class="flex-1 flex items-center justify-center gap-2 py-1.5 text-xs font-medium bg-indigo-600 hover:bg-indigo-500 text-white rounded transition-all shadow-lg shadow-indigo-900/20"
|
|
>
|
|
<Plus class="w-3.5 h-3.5" /> New Request
|
|
</button>
|
|
<button
|
|
@click="store.clearHistory()"
|
|
class="flex-none flex items-center justify-center gap-2 px-3 py-1.5 text-xs font-medium bg-slate-800 hover:bg-red-500/10 hover:text-red-400 text-slate-400 rounded transition-all border border-slate-700 hover:border-red-500/50"
|
|
title="Clear History"
|
|
>
|
|
<Trash class="w-3.5 h-3.5" />
|
|
</button>
|
|
</div>
|
|
|
|
<!-- History List -->
|
|
<div class="flex-1 overflow-y-auto">
|
|
<div v-if="store.history.length === 0" class="p-8 text-center text-slate-600 text-xs">
|
|
No history yet. Make a request!
|
|
</div>
|
|
<div v-else class="flex flex-col">
|
|
<button
|
|
v-for="item in store.history"
|
|
:key="item.id"
|
|
@click="store.loadRequest(item)"
|
|
class="group flex flex-col text-left px-3 py-2 border-b border-slate-800/50 hover:bg-slate-900 transition-colors w-full"
|
|
>
|
|
<!-- First Row: Method, Status, Delete Button -->
|
|
<div class="flex items-center justify-between w-full">
|
|
<div class="flex items-center gap-2">
|
|
<MethodBadge :method="item.method" />
|
|
|
|
<!-- Status Badge -->
|
|
<span
|
|
v-if="item.response?.status"
|
|
class="text-[10px] font-mono font-bold px-1.5 py-0.5 rounded-full"
|
|
:class="getStatusColor(item.response?.status)"
|
|
>
|
|
{{ item.response.status }}
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Delete Button -->
|
|
<button
|
|
@click.stop="store.deleteHistoryItem(item.id)"
|
|
class="opacity-0 group-hover:opacity-100 transition-opacity p-1.5 text-slate-500 hover:text-red-400 hover:bg-slate-800 rounded-md cursor-pointer flex-shrink-0"
|
|
>
|
|
<Trash2 class="w-3.5 h-3.5" />
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Second Row: URL -->
|
|
<div class="mt-1">
|
|
<span class="text-xs text-slate-400 truncate font-medium block" :title="item.url">
|
|
{{ item.url || '/' }}
|
|
</span>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Settings -->
|
|
<div class="p-2 border-t border-slate-800">
|
|
<button
|
|
@click="emit('open-settings')"
|
|
class="w-full flex items-center gap-2 px-3 py-2 text-xs font-medium text-slate-400 hover:text-slate-200 hover:bg-slate-900 rounded transition-colors"
|
|
>
|
|
<Settings class="w-4 h-4" /> Settings
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
</template>
|