This commit is contained in:
Adrian Hopek
2022-01-18 07:39:03 +01:00
parent 7dca5d1e6c
commit acf2eba95d
17 changed files with 644 additions and 32 deletions

View File

@@ -1,3 +1,49 @@
@import 'flatpickr/dist/themes/light.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg {
fill: #4F46E5;
}
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected.inRange,
.flatpickr-day.startRange.inRange,
.flatpickr-day.endRange.inRange,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange:focus,
.flatpickr-day.endRange:focus,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.selected.prevMonthDay,
.flatpickr-day.startRange.prevMonthDay,
.flatpickr-day.endRange.prevMonthDay,
.flatpickr-day.selected.nextMonthDay,
.flatpickr-day.startRange.nextMonthDay,
.flatpickr-day.endRange.nextMonthDay {
background: #527ABA;
-webkit-box-shadow: none;
box-shadow: none;
color: #fff;
border-color: #527ABA;
}
.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)),
.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)),
.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)) {
-webkit-box-shadow: -10px 0 0 #527ABA;
box-shadow: -10px 0 0 #527ABA;
}
.flatpickr-day.week.selected {
border-radius: 0;
-webkit-box-shadow: -5px 0 0 #527ABA, 5px 0 0 #527ABA;
box-shadow: -5px 0 0 #527ABA, 5px 0 0 #527ABA;
}

View File

@@ -0,0 +1,162 @@
<template>
<InertiaHead title="Dodawanie użytkownika" />
<div class="bg-white sm:rounded-lg shadow-md">
<div class="p-4 sm:px-6">
<h2 class="text-lg leading-6 font-medium text-gray-900">
Dodaj użytkownika
</h2>
<p class="mt-1 text-sm text-gray-500">
Tylko dodani użytkownicy będą mogli zalogować się do aplikacji.
</p>
</div>
<form
class="border-t border-gray-200 px-6 divide-y"
@submit.prevent="form.post('/users')"
>
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
<label
for="name"
class="block text-sm font-medium text-gray-700 sm:mt-px"
>
Imię i nazwisko
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<input
id="name"
v-model="form.name"
type="text"
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.name, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.name }"
>
<p
v-if="form.errors.name"
class="mt-2 text-sm text-red-600"
>
{{ form.errors.name }}
</p>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
<label
for="email"
class="block text-sm font-medium text-gray-700 sm:mt-px"
>
Adres email
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<input
id="email"
v-model="form.email"
type="email"
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.email, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.email }"
>
<p
v-if="form.errors.email"
class="mt-2 text-sm text-red-600"
>
{{ form.errors.email }}
</p>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
<label
for="employment_form"
class="block text-sm font-medium text-gray-700 sm:mt-px"
>
Forma zatrudnienia
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<select
id="employment_form"
v-model="form.employmentForm"
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.employmentForm, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.employmentForm }"
>
<option
v-for="employmentForm in employmentForms"
:key="employmentForm.value"
:value="employmentForm.value"
>
{{ employmentForm.label }}
</option>
</select>
<p
v-if="form.errors.employmentForm"
class="mt-2 text-sm text-red-600"
>
{{ form.errors.employmentForm }}
</p>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
<label
for="employment_date"
class="block text-sm font-medium text-gray-700 sm:mt-px"
>
Data zatrudnienia
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<FlatPickr
id="employment_date"
v-model="form.employmentDate"
placeholder="Wybierz datę"
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.employmentDate, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.employmentDate }"
/>
<p
v-if="form.errors.employmentDate"
class="mt-2 text-sm text-red-600"
>
{{ form.errors.employmentDate }}
</p>
</div>
</div>
<div class="flex justify-end py-3">
<div class="space-x-3">
<InertiaLink
href="/users"
class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
>
Anuluj
</InertiaLink>
<button
type="submit"
:disabled="form.processing"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blumilk-600 hover:bg-blumilk-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
>
Zapisz
</button>
</div>
</div>
</form>
</div>
</template>
<script>
import {useForm} from '@inertiajs/inertia-vue3';
import FlatPickr from 'vue-flatpickr-component';
export default {
employmentDate: 'UserCreate',
components: {
FlatPickr,
},
props: {
employmentForms: {
type: Object,
default: () => null,
},
},
setup(props) {
const form = useForm({
name: null,
email: null,
employmentForm: props.employmentForms[0].value,
employmentDate: new Date(),
});
return { form };
}
};
</script>

View File

@@ -0,0 +1,166 @@
<template>
<InertiaHead title="Edycja użytkownika" />
<div class="bg-white sm:rounded-lg shadow-md">
<div class="p-4 sm:px-6">
<h2 class="text-lg leading-6 font-medium text-gray-900">
Edytuj użytkownika
</h2>
<p class="mt-1 text-sm text-gray-500">
Edytuj dane użytkownika, takie jak email czy formę zatrudnienia.
</p>
</div>
<form
class="border-t border-gray-200 px-6 divide-y"
@submit.prevent="form.put(`/users/${user.id}`)"
>
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
<label
for="name"
class="block text-sm font-medium text-gray-700 sm:mt-px"
>
Imię i nazwisko
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<input
id="name"
v-model="form.name"
type="text"
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.name, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.name }"
>
<p
v-if="form.errors.name"
class="mt-2 text-sm text-red-600"
>
{{ form.errors.name }}
</p>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
<label
for="email"
class="block text-sm font-medium text-gray-700 sm:mt-px"
>
Adres email
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<input
id="email"
v-model="form.email"
type="email"
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.email, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.email }"
>
<p
v-if="form.errors.email"
class="mt-2 text-sm text-red-600"
>
{{ form.errors.email }}
</p>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
<label
for="employment_form"
class="block text-sm font-medium text-gray-700 sm:mt-px"
>
Forma zatrudnienia
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<select
id="employment_form"
v-model="form.employmentForm"
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.employmentForm, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.employmentForm }"
>
<option
v-for="employmentForm in employmentForms"
:key="employmentForm.value"
:value="employmentForm.value"
>
{{ employmentForm.label }}
</option>
</select>
<p
v-if="form.errors.employmentForm"
class="mt-2 text-sm text-red-600"
>
{{ form.errors.employmentForm }}
</p>
</div>
</div>
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
<label
for="employment_date"
class="block text-sm font-medium text-gray-700 sm:mt-px"
>
Data zatrudnienia
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<FlatPickr
id="employment_date"
v-model="form.employmentDate"
placeholder="Wybierz datę"
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.employmentDate, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.employmentDate }"
/>
<p
v-if="form.errors.employmentDate"
class="mt-2 text-sm text-red-600"
>
{{ form.errors.employmentDate }}
</p>
</div>
</div>
<div class="flex justify-end py-3">
<div class="space-x-3">
<InertiaLink
href="/users"
class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
>
Anuluj
</InertiaLink>
<button
type="submit"
:disabled="form.processing"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blumilk-600 hover:bg-blumilk-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
>
Zapisz
</button>
</div>
</div>
</form>
</div>
</template>
<script>
import {useForm} from '@inertiajs/inertia-vue3';
import FlatPickr from 'vue-flatpickr-component';
export default {
employmentDate: 'UserEdit',
components: {
FlatPickr,
},
props: {
employmentForms: {
type: Object,
default: () => null,
},
user: {
type: Object,
default: () => null,
},
},
setup(props) {
const form = useForm({
name: props.user.name,
email: props.user.email,
employmentForm: props.user.employmentForm,
employmentDate: new Date(props.user.employmentDate),
});
return { form };
}
};
</script>

View File

@@ -1,13 +1,23 @@
<template>
<InertiaHead title="Użytkownicy" />
<div class="bg-white sm:rounded-lg shadow-md">
<div class="p-4 sm:px-6">
<h2 class="text-lg leading-6 font-medium text-gray-900">
Użytkownicy w organizacji
</h2>
<p class="mt-1 text-sm text-gray-500">
Lista użytkowników w organizacji.
</p>
<div class="flex justify-between items-center p-4 sm:px-6">
<div>
<h2 class="text-lg leading-6 font-medium text-gray-900">
Użytkownicy w organizacji
</h2>
<p class="mt-1 text-sm text-gray-500">
Lista użytkowników w organizacji.
</p>
</div>
<div>
<InertiaLink
href="users/create"
class="inline-flex items-center px-4 py-3 border border-transparent text-sm leading-4 font-medium rounded-md shadow-sm text-white bg-blumilk-600 hover:bg-blumilk-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
>
Dodaj użytkownika
</InertiaLink>
</div>
</div>
<div class="border-t border-gray-200">
<div class="px-4 py-3">
@@ -61,7 +71,7 @@
<tr
v-for="user in users.data"
:key="user.id"
class="hover:bg-white"
:class="{ 'bg-red-50': user.trashed, 'hover:bg-blumilk-25': !user.trashed }"
>
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
<div class="flex">
@@ -91,25 +101,72 @@
{{ user.employmentForm }}
</td>
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
{{ user.employmentStartDate }}
{{ user.employmentDate }}
</td>
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500 text-right">
<div>
<button
class="rounded-full flex items-center text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-blumilk-500"
>
<svg
<Menu
as="div"
class="relative inline-block text-left"
>
<MenuButton class="rounded-full flex items-center text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-blumilk-500">
<DotsVerticalIcon
class="h-5 w-5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"
/>
</svg>
</button>
</div>
aria-hidden="true"
/>
</MenuButton>
<transition
enter-active-class="transition ease-out duration-100"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95"
>
<MenuItems class="origin-top-right absolute right-0 mt-2 w-56 z-10 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
<div
v-if="!user.trashed"
class="py-1"
>
<MenuItem v-slot="{ active }">
<InertiaLink
:href="`/users/${user.id}/edit`"
:class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block px-4 py-2 text-sm']"
>
Edytuj
</InertiaLink>
</MenuItem>
<MenuItem v-slot="{ active }">
<InertiaLink
as="button"
method="delete"
:preserve-scroll="true"
:href="`/users/${user.id}`"
:class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block w-full text-left px-4 py-2 text-sm']"
>
Usuń
</InertiaLink>
</MenuItem>
</div>
<div
v-else
class="py-1"
>
<MenuItem v-slot="{ active }">
<InertiaLink
as="button"
method="post"
:preserve-scroll="true"
:href="`/users/${user.id}/restore`"
:class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block w-full text-left px-4 py-2 text-sm']"
>
Przywróć
</InertiaLink>
</MenuItem>
</div>
</MenuItems>
</transition>
</Menu>
</td>
</tr>
<tr
@@ -162,6 +219,7 @@
<Component
:is="link.url ? 'InertiaLink' : 'span'"
:href="link.url"
:preserve-scroll="true"
class="relative inline-flex items-center px-4 py-2 border rounded-md text-sm font-medium"
:class="{ 'z-10 bg-blumilk-25 border-blumilk-500 text-blumilk-600': link.active, 'bg-white border-gray-300 text-gray-500': !link.active, 'hover:bg-blumilk-25': link.url, 'border-none': !link.url}"
v-text="link.label"
@@ -180,11 +238,18 @@ import { ref, watch } from 'vue';
import { Inertia } from '@inertiajs/inertia';
import { debounce } from 'lodash';
import { SearchIcon } from '@heroicons/vue/outline';
import {DotsVerticalIcon} from '@heroicons/vue/solid';
import {Menu, MenuButton, MenuItem, MenuItems} from '@headlessui/vue';
export default {
name: 'UserIndex',
components: {
SearchIcon,
DotsVerticalIcon,
Menu,
MenuButton,
MenuItem,
MenuItems,
},
props: {
users: {

View File

@@ -2,6 +2,8 @@ import {createApp, h} from 'vue';
import {createInertiaApp, Head, Link} from '@inertiajs/inertia-vue3';
import {InertiaProgress} from '@inertiajs/progress';
import AppLayout from '@/Shared/Layout/AppLayout';
import Flatpickr from 'flatpickr';
import { Polish } from 'flatpickr/dist/l10n/pl.js';
createInertiaApp({
resolve: name => {
@@ -25,3 +27,12 @@ InertiaProgress.init({
delay: 0,
color: 'red',
});
Flatpickr.localize(Polish);
Flatpickr.setDefaults({
dateFormat: 'Y-m-d',
enableTime: false,
altFormat: 'j F Y',
altInput: true
});