Files
ytp/client/src/components/LoginView.svelte
2025-11-03 22:54:10 +03:00

304 lines
6.1 KiB
Svelte

<script>
import { createEventDispatcher } from 'svelte';
import { login } from '../api';
const dispatch = createEventDispatcher();
let username = '';
let password = '';
let loading = false;
let error = '';
const sampleUsers = [
{
role: 'Admin',
username: 'admin',
password: 'Admin!123',
description: 'Mal sorumlularini olusturur ve butun kayitlara erisir.'
},
{
role: 'Yakit sorumlusu',
username: 'yakitsorum',
password: 'Yakit@123',
description: 'Yakit teslimlerini ve sarfiyatini takip eder.'
},
{
role: 'Mal sorumlusu',
username: 'malsorum1',
password: 'Mal@123',
description: 'Depodaki ekipman ve sarf malzemelerini raporlar.'
}
];
async function handleSubmit(event) {
event.preventDefault();
error = '';
if (!username || !password) {
error = 'Kullanici adi ve sifre girilmeli.';
return;
}
loading = true;
try {
const response = await login({ username, password });
dispatch('success', response);
} catch (err) {
error = err.message;
} finally {
loading = false;
}
}
function fillSample(sample) {
username = sample.username;
password = sample.password;
error = '';
}
</script>
<div class="login">
<div class="intro">
<h2>Hos geldiniz</h2>
<p>
Akaryakit istasyonunda rolunuze uygun kontrol paneline erismek icin lutfen bilgilerinizi girin.
</p>
</div>
<form class="form" on:submit|preventDefault={handleSubmit}>
<label>
<span>Kullanici adi</span>
<input
autocomplete="username"
name="username"
placeholder="ornek: admin"
bind:value={username}
required
/>
</label>
<label>
<span>Sifre</span>
<input
type="password"
name="password"
autocomplete="current-password"
placeholder="ornek: Admin!123"
bind:value={password}
required
/>
</label>
{#if error}
<div class="error">{error}</div>
{/if}
<button type="submit" disabled={loading}>
{#if loading}
Giris yapiliyor...
{:else}
Giris yap
{/if}
</button>
</form>
<div class="samples">
<h3>Ornek kullanicilar</h3>
<div class="sample-grid">
{#each sampleUsers as sample}
<article class="sample-card">
<header>
<span class="tag">{sample.role}</span>
<button type="button" on:click={() => fillSample(sample)}>
<i class="fa-solid fa-right-to-bracket" aria-hidden="true"></i>
Doldur
</button>
</header>
<dl>
<div>
<dt>Kullanici adi</dt>
<dd>{sample.username}</dd>
</div>
<div>
<dt>Sifre</dt>
<dd>{sample.password}</dd>
</div>
</dl>
<p>{sample.description}</p>
</article>
{/each}
</div>
</div>
</div>
<style>
.login {
display: grid;
gap: 2rem;
}
.intro h2 {
margin: 0;
font-size: 2rem;
color: #1f2d44;
}
.intro p {
margin: 0.5rem 0 0;
color: #4b5a78;
}
.form {
display: grid;
gap: 1rem;
max-width: 420px;
}
label {
display: grid;
gap: 0.35rem;
font-weight: 600;
color: #27334f;
}
input {
border-radius: 12px;
border: 1px solid rgba(126, 143, 191, 0.4);
padding: 0.85rem 1rem;
font-size: 1rem;
background: #fdfdff;
color: #1f2d44;
transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}
input::placeholder {
color: rgba(123, 139, 180, 0.7);
}
input:focus {
border-color: #4c6ef5;
box-shadow: 0 0 0 3px rgba(76, 110, 245, 0.2);
background: #ffffff;
outline: none;
}
button[type='submit'] {
background: linear-gradient(135deg, #ff7a45, #ff9a5d);
color: #ffffff;
padding: 0.9rem 1rem;
border-radius: 12px;
font-weight: 600;
border: none;
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
box-shadow: 0 18px 28px rgba(255, 111, 60, 0.35);
}
button[type='submit']:hover {
transform: translateY(-1px);
box-shadow: 0 22px 36px rgba(255, 111, 60, 0.45);
}
button[type='submit'][disabled] {
background: #bcc4d9;
cursor: wait;
box-shadow: none;
}
.error {
background: rgba(255, 107, 107, 0.12);
color: #ff9a9a;
border-radius: 12px;
border: 1px solid rgba(255, 138, 138, 0.35);
padding: 0.75rem 1rem;
font-weight: 500;
}
.samples h3 {
margin: 0 0 1rem;
font-size: 1.1rem;
color: #1f2d44;
}
.sample-grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.sample-card {
border: 1px solid #dee5f5;
border-radius: 18px;
padding: 1.35rem;
background: linear-gradient(135deg, #ffffff, #f6f8ff);
box-shadow: 0 18px 32px rgba(88, 115, 173, 0.16);
display: flex;
flex-direction: column;
gap: 0.75rem;
color: #2a3856;
}
.sample-card header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 0.5rem;
}
.sample-card header button {
border: 1px solid #d2dcf3;
background: #edf2ff;
color: #4357b2;
border-radius: 999px;
padding: 0.35rem 1rem;
font-size: 0.85rem;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 0.35rem;
}
.sample-card header button:hover {
border-color: #4357b2;
}
.tag {
background: rgba(76, 110, 245, 0.12);
color: #354fa8;
text-transform: uppercase;
letter-spacing: 0.03em;
font-size: 0.75rem;
font-weight: 600;
padding: 0.2rem 0.75rem;
border-radius: 999px;
}
dl {
margin: 0;
display: grid;
gap: 0.25rem;
font-family: 'Roboto Mono', monospace;
font-size: 0.85rem;
color: #3c4c6e;
}
dt {
font-weight: 600;
color: #6a7796;
}
dd {
margin: 0;
color: #1f2d44;
font-size: 0.95rem;
}
.sample-card p {
margin: 0;
color: #556582;
font-size: 0.9rem;
line-height: 1.4;
}
</style>