Вывалил функционал по добавлению записей в журнал компьютера + несколько микрофиксов и рефакторинг
This commit is contained in:
parent
f64ea3c5e3
commit
f48de37c37
|
@ -14,15 +14,26 @@ class JobController extends Controller
|
|||
}
|
||||
|
||||
public function getByComputerId(Request $request){
|
||||
$request->validate([
|
||||
'computer_id' => 'required|exists:computers,id'
|
||||
]);
|
||||
return Job::select()->where('computer_id', '=', $request->get('computer_id'))->get();
|
||||
}
|
||||
|
||||
public function getById(Request $request){
|
||||
$request->validate([
|
||||
'id' => 'required|exists:jobs,id'
|
||||
]);
|
||||
return Job::find($request->get('id'));
|
||||
// return Job::select()->where('id', '=', $request->get('id'))->get();
|
||||
}
|
||||
|
||||
public function create(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'computer_id' => 'required|exists:computers,id',
|
||||
'description' => 'required|string|max:256',
|
||||
'status' => 'nullable|boolean'
|
||||
'status' => 'required|string|max:256'
|
||||
]);
|
||||
|
||||
$job = Job::create($request->all());
|
||||
|
@ -35,7 +46,7 @@ class JobController extends Controller
|
|||
'id' => 'required|exists:jobs,id',
|
||||
'computer_id' => 'required|exists:computers,id',
|
||||
'description' => 'required|string|max:256',
|
||||
'status' => 'nullable|boolean'
|
||||
'status' => 'required|string|max:256'
|
||||
]);
|
||||
|
||||
$job = Job::find($request->get('id'));
|
||||
|
|
|
@ -16,7 +16,7 @@ return new class extends Migration
|
|||
$table->unsignedBigInteger('computer_id');
|
||||
$table->foreign('computer_id')->references('id')->on('computers');
|
||||
$table->string('description', length: 256);
|
||||
$table->boolean('status')->default(false);
|
||||
$table->string('status', length: 256);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -89,7 +89,6 @@ export default {
|
|||
mounted() {
|
||||
this.resizeEventHandler();
|
||||
window.addEventListener("resize", this.resizeEventHandler, { passive: true });
|
||||
this.userStore.checkUser();
|
||||
watch(this.userStore, (newStore)=>{
|
||||
this.authenticated = newStore.user !== null && newStore.user !== undefined;
|
||||
if (!this.authenticated){
|
||||
|
@ -98,6 +97,7 @@ export default {
|
|||
this.$router.push('/');
|
||||
}
|
||||
});
|
||||
this.userStore.checkUser();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -33,6 +33,7 @@ export const useUserStore = defineStore('user', {
|
|||
})
|
||||
},
|
||||
async login(email, password, rememberMe) {
|
||||
let responce = false;
|
||||
await axios.post(
|
||||
'/api/auth/login',
|
||||
{
|
||||
|
@ -42,15 +43,17 @@ export const useUserStore = defineStore('user', {
|
|||
}).then((res) => {
|
||||
this.setUser(res.data.user);
|
||||
this.setToken(res.data.accessToken);
|
||||
return true;
|
||||
responce = true;
|
||||
}).catch((error) => {
|
||||
if (!error.response) {
|
||||
return false;
|
||||
responce = false;
|
||||
}
|
||||
return error.response.data.message;
|
||||
responce = error.response.data.message;
|
||||
})
|
||||
return responce;
|
||||
},
|
||||
async registration(login, email, password, repeatPassword) {
|
||||
let responce = false;
|
||||
await axios.post(
|
||||
'/api/auth/register',
|
||||
{
|
||||
|
@ -61,13 +64,14 @@ export const useUserStore = defineStore('user', {
|
|||
}).then((res) => {
|
||||
this.setUser(res.data.user);
|
||||
this.setToken(res.data.accessToken);
|
||||
return true;
|
||||
responce = true;
|
||||
}).catch((error) => {
|
||||
if (!error.response) {
|
||||
return false;
|
||||
responce = false;
|
||||
}
|
||||
return error.response.data.message;
|
||||
responce= error.response.data.message;
|
||||
})
|
||||
return responce;
|
||||
},
|
||||
logout() {
|
||||
axios.get('/api/auth/logout',
|
||||
|
|
|
@ -12,9 +12,11 @@ export const useComputersStore = defineStore('computers', {
|
|||
this.token = token;
|
||||
localStorage.setItem('auth_token', token);
|
||||
},
|
||||
|
||||
checkToken(){
|
||||
this.token = useUserStore().token;
|
||||
},
|
||||
|
||||
async getById(id){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
|
@ -36,6 +38,7 @@ export const useComputersStore = defineStore('computers', {
|
|||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
async getComputerList(user_id){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
|
@ -55,6 +58,114 @@ export const useComputersStore = defineStore('computers', {
|
|||
this.computers = response.data;
|
||||
})
|
||||
},
|
||||
|
||||
async getJobsByComputerId(computerId){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
}
|
||||
let result = null;
|
||||
await axios.get(
|
||||
'/api/data/jobs/byComputer',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
token: this.token
|
||||
},
|
||||
params: {
|
||||
computer_id: computerId
|
||||
}
|
||||
}
|
||||
).then((response)=>{
|
||||
result = response.data;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
async getJobsById(id){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
}
|
||||
let result = null;
|
||||
await axios.get(
|
||||
'/api/data/jobs/byId',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
token: this.token
|
||||
},
|
||||
params: {
|
||||
id: id
|
||||
}
|
||||
}
|
||||
).then((response)=>{
|
||||
result = response.data;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
async createJob(computerId, description, status){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
}
|
||||
await axios.post('/api/data/jobs/create', {
|
||||
computer_id: computerId,
|
||||
description: description,
|
||||
status: status
|
||||
}, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
token: this.token
|
||||
},
|
||||
}).then(()=>{
|
||||
return true;
|
||||
}).catch(()=>{
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
async updateJob(id, computerId, description, status){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
}
|
||||
await axios.post('/api/data/jobs/save', {
|
||||
id: id,
|
||||
computer_id: computerId,
|
||||
description: description,
|
||||
status: status
|
||||
}, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
token: this.token
|
||||
},
|
||||
}).then(()=>{
|
||||
this.getComputerList(useUserStore().user['id']);
|
||||
return true;
|
||||
}).catch(()=>{
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
async deleteJob(id){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
}
|
||||
let result = false;
|
||||
await axios.post('/api/data/jobs/delete', {
|
||||
id: id,
|
||||
}, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
token: this.token
|
||||
},
|
||||
}).then(()=>{
|
||||
this.getComputerList(useUserStore().user['id']);
|
||||
result = true;
|
||||
}).catch(()=>{
|
||||
result = false;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
async create(name, cpu, ram, motherboard, gpu, additional_info){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
|
@ -79,6 +190,7 @@ export const useComputersStore = defineStore('computers', {
|
|||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
async update(id, name, cpu, ram, motherboard, gpu, additional_info){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
|
@ -103,6 +215,7 @@ export const useComputersStore = defineStore('computers', {
|
|||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
async delete(id){
|
||||
if (this.token === null){
|
||||
this.checkToken();
|
||||
|
|
|
@ -78,10 +78,10 @@ export default {
|
|||
<template>
|
||||
<v-card class="main-bg">
|
||||
<v-card-title class="d-flex justify-space-between">
|
||||
<span>Создание нового компьютера</span>
|
||||
<span>Изменение компьютера</span>
|
||||
<v-icon @click="dialogClose" class="cursor-pointer" icon="mdi-close-thick"></v-icon>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-card-text>
|
||||
<v-skeleton-loader color="grey-darken-4" type="card" v-if="fetching"></v-skeleton-loader>
|
||||
<div v-if="!fetching">
|
||||
<v-text-field :rules="[rules.notNull]" label="Название" v-model="computerName" placeholder="Мой компьютер"></v-text-field>
|
||||
|
@ -99,4 +99,4 @@ export default {
|
|||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -52,7 +52,7 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
this.userStore.checkUser();
|
||||
this.computerList = this.computersStore.computers;
|
||||
watch(this.userStore, (newStore)=>{
|
||||
this.fetching = true;
|
||||
this.authenticated = newStore.user !== null && newStore.user !== undefined;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<script>
|
||||
import { useComputersStore } from '../../store/computers';
|
||||
import {rules} from '../../js/rules.js'
|
||||
|
||||
export default {
|
||||
name: "CreateJobForm",
|
||||
computed: {
|
||||
rules() {
|
||||
return rules
|
||||
}
|
||||
},
|
||||
props: {
|
||||
dialogClose: Function,
|
||||
computerId: Number
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
jobDescription: null,
|
||||
jobStatus: null,
|
||||
loading: false,
|
||||
computersStore: useComputersStore()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
createJob(){
|
||||
this.loading = true;
|
||||
if (!rules.notNull(this.jobDescription) || !rules.notNull(this.jobStatus)){
|
||||
alert('Описание и статус необходимо заполнить');
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
this.computersStore.createJob(
|
||||
this.computerId,
|
||||
this.jobDescription,
|
||||
this.jobStatus
|
||||
).then((result)=>{
|
||||
this.loading = false;
|
||||
this.dialogClose();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card class="main-bg">
|
||||
<v-card-title class="d-flex justify-space-between">
|
||||
<span>Новая запись</span>
|
||||
<v-icon @click="dialogClose" class="cursor-pointer" icon="mdi-close-thick"></v-icon>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea label="Описание" v-model="jobDescription" placeholder="Замена термопасты 02.03.2025"></v-textarea>
|
||||
<v-text-field label="Статус" v-model="jobStatus" placeholder="В работе"></v-text-field>
|
||||
<div class="d-flex justify-center">
|
||||
<v-btn color="#F0A068FF" :loading="loading" @click="createJob">Создать</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,88 @@
|
|||
<script>
|
||||
import { useComputersStore } from '../../store/computers.js';
|
||||
import {rules} from '../../js/rules.js';
|
||||
import {toRef, ref} from "vue";
|
||||
|
||||
export default {
|
||||
name: "EditJobForm",
|
||||
computed: {
|
||||
rules() {
|
||||
return rules
|
||||
}
|
||||
},
|
||||
props: {
|
||||
dialogClose: Function,
|
||||
computerId: Number,
|
||||
jobId: Number
|
||||
},
|
||||
setup(props) {
|
||||
const id = toRef(props, 'computer_id')
|
||||
},
|
||||
mounted() {
|
||||
this.fetching = true;
|
||||
this.computersStore.getJobsById(this.jobId).then((responce)=>{
|
||||
this.jobToEdit = responce;
|
||||
console.log(this.jobToEdit)
|
||||
this.jobDescription = this.jobToEdit['description'];
|
||||
this.jobStatus = this.jobToEdit['status'];
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
jobToEdit: null,
|
||||
jobDescription: null,
|
||||
jobStatus: null,
|
||||
loading: false,
|
||||
fetching: false,
|
||||
computersStore: useComputersStore()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
editJob(){
|
||||
this.loading = true;
|
||||
if (!rules.notNull(this.computerId) || this.computerId === 0 || !rules.notNull(this.jobId) || this.jobId === 0){
|
||||
alert('Произошла ошибка');
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
if (!rules.notNull(this.jobDescription) || !rules.notNull(this.jobStatus)){
|
||||
alert('Описание и статус необходимо заполнить');
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
this.computersStore.updateJob(
|
||||
this.jobId,
|
||||
this.computerId,
|
||||
this.jobDescription,
|
||||
this.jobStatus
|
||||
).then((result)=>{
|
||||
this.loading = false;
|
||||
this.dialogClose();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card class="main-bg">
|
||||
<v-card-title class="d-flex justify-space-between">
|
||||
<span>Изменение записи</span>
|
||||
<v-icon @click="dialogClose" class="cursor-pointer" icon="mdi-close-thick"></v-icon>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-skeleton-loader color="grey-darken-4" type="card" v-if="fetching"></v-skeleton-loader>
|
||||
<div v-if="!fetching">
|
||||
<v-textarea label="Описание" v-model="jobDescription" placeholder="Замена термопасты 02.03.2025"></v-textarea>
|
||||
<v-text-field label="Статус" v-model="jobStatus" placeholder="В работе"></v-text-field>
|
||||
<div class="d-flex justify-center">
|
||||
<v-btn color="#F0A068FF" :loading="loading" @click="editJob">Сохранить</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -1,20 +1,86 @@
|
|||
<script>
|
||||
import {useUserStore} from "../store/auth.js";
|
||||
import {useComputersStore} from "../store/computers.js";
|
||||
import {ref, watch} from "vue";
|
||||
import CreateJobForm from "./Jobs/CreateJobForm.vue";
|
||||
import EditJobForm from "./Jobs/EditJobForm.vue";
|
||||
|
||||
export default {
|
||||
name: "JobsList",
|
||||
components: {EditJobForm, CreateJobForm},
|
||||
data() {
|
||||
return {
|
||||
userStore: useUserStore(),
|
||||
computersStore: useComputersStore(),
|
||||
computerId: null,
|
||||
fetching: false,
|
||||
authenticated: false
|
||||
authenticated: false,
|
||||
jobs: [],
|
||||
createDialogShow: false,
|
||||
editDialogShow: false,
|
||||
jobToEditId: ref(0),
|
||||
deleteDialogShow: false,
|
||||
deleteLoading: false,
|
||||
jobToDeleteId: ref(0)
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.computerId = this.$route.query.id;
|
||||
this.fetching = true;
|
||||
this.computersStore.getJobsByComputerId(this.computerId).then((response)=>{
|
||||
this.jobs = response;
|
||||
this.fetching = false;
|
||||
});
|
||||
watch(this.computersStore, (newStore)=>{
|
||||
this.fetching = true;
|
||||
newStore.getJobsByComputerId(this.computerId).then((response)=>{
|
||||
this.jobs = response;
|
||||
this.fetching = false;
|
||||
});
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
updateJobList(){
|
||||
this.fetching = true;
|
||||
this.computersStore.getJobsByComputerId(this.computerId).then((response)=>{
|
||||
this.jobs = response;
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
showCreateDialog(){
|
||||
this.createDialogShow = true;
|
||||
},
|
||||
closeCreateDialog(){
|
||||
this.createDialogShow = false;
|
||||
this.updateJobList();
|
||||
},
|
||||
showEditDialog(id){
|
||||
this.jobToEditId = id;
|
||||
this.editDialogShow = true;
|
||||
},
|
||||
closeEditDialog(){
|
||||
this.editDialogShow = false;
|
||||
this.updateJobList();
|
||||
},
|
||||
showDeleteDialog(id){
|
||||
this.jobToDeleteId = id;
|
||||
this.deleteDialogShow = true;
|
||||
},
|
||||
closeDeleteDialog(){
|
||||
this.deleteDialogShow = false;
|
||||
this.updateJobList();
|
||||
},
|
||||
deleteComputer(){
|
||||
this.deleteLoading = true;
|
||||
this.computersStore.deleteJob(this.jobToDeleteId).then((responce)=>{
|
||||
this.deleteLoading = false;
|
||||
if (responce){
|
||||
this.closeDeleteDialog();
|
||||
} else {
|
||||
alert('Произошла ошибка')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -25,12 +91,51 @@ export default {
|
|||
<v-btn color="#F0A068FF">Назад</v-btn>
|
||||
</router-link>
|
||||
<v-skeleton-loader v-if="fetching" color="grey-darken-3" class="w-100" type="card"/>
|
||||
<div v-if="!fetching">
|
||||
|
||||
<div v-if="!fetching" class="pt-3 pb-3">
|
||||
<div class="d-flex mb-2" v-for="job in jobs">
|
||||
<v-card class="card-bg text-decoration-none w-100">
|
||||
<v-card-title>{{ job['description'] }}</v-card-title>
|
||||
<v-card-text class="d-flex flex-column cursor-pointer">
|
||||
<label>Статус: {{ job['status'] }}</label>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<div @click="showEditDialog(job['id'])" class="card-bg align-self-stretch pa-2 d-flex justify-center align-center rounded-sm cursor-pointer mr-2 ml-2">
|
||||
<v-icon icon="mdi-pencil"></v-icon>
|
||||
</div>
|
||||
<div @click="showDeleteDialog(job['id'])" class="card-bg align-self-stretch pa-2 d-flex justify-center align-center rounded-sm cursor-pointer mr-2 ml-2">
|
||||
<v-icon icon="mdi-trash-can"></v-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-100 pa-5" v-if="!fetching">
|
||||
<v-btn class="w-100" color="#F0A068FF" @click="showCreateDialog" rounded="xs">
|
||||
<v-icon icon="mdi-plus-thick"></v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
<v-dialog v-model="createDialogShow">
|
||||
<CreateJobForm :dialogClose="closeCreateDialog" :computerId="computerId"/>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="editDialogShow">
|
||||
<EditJobForm :dialogClose="closeEditDialog" :computerId="computerId" :jobId="jobToEditId"/>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="deleteDialogShow" class="w-33">
|
||||
<v-card class="main-bg">
|
||||
<v-card-text class="d-flex flex-column">
|
||||
<v-label class="w-100 text-h5">Вы уверены?</v-label>
|
||||
<v-label class="w-100">Это действие удалит запись</v-label>
|
||||
<div class="d-flex w-100 justify-center">
|
||||
<v-btn color="#F0A068FF" class="ma-2" :loading="deleteLoading" @click="deleteComputer">Да</v-btn>
|
||||
<v-btn color="#F0A068FF" class="ma-2" @click="closeDeleteDialog">Нет</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.card-bg {
|
||||
background-color: #272727 !important;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
@click:append="showPassword = !showPassword"
|
||||
required></v-text-field>
|
||||
<v-checkbox v-model="rememberMe" label="Запомнить меня"></v-checkbox>
|
||||
<v-label style="color: red" :style="errorMessageContainerStyle">{{ errorMessage }}</v-label>
|
||||
<div class="d-flex justify-center" :class="isWide ? '' : 'flex-column align-center'">
|
||||
<v-btn type="submit" color="#F0A068FF" class="ma-5 flex-grow-0" :class="isWide ? 'w-25' : 'w-100 text-body-1'" :loading="loading">Войти</v-btn>
|
||||
<router-link to="/register" class="text-decoration-none link-no-color ma-5" :class="isWide ? 'w-25' : 'w-100'">
|
||||
|
@ -53,7 +54,6 @@ export default {
|
|||
if (isLogged){
|
||||
this.errorMessage = '';
|
||||
this.errorMessageContainerStyle = 'display: none;';
|
||||
this.$router.push('/');
|
||||
} else {
|
||||
this.errorMessage = 'Authentication error';
|
||||
this.errorMessageContainerStyle = '';
|
||||
|
@ -63,7 +63,6 @@ export default {
|
|||
this.errorMessageContainerStyle = '';
|
||||
}
|
||||
});
|
||||
this.$router.push('/');
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ export default {
|
|||
if (isRegistred){
|
||||
this.errorMessage = '';
|
||||
this.errorMessageContainerStyle = 'display: none;';
|
||||
this.$router.push('/');
|
||||
} else {
|
||||
this.errorMessage = 'Registration error';
|
||||
this.errorMessageContainerStyle = '';
|
||||
|
|
|
@ -44,6 +44,7 @@ Route::group(['prefix' => 'data'], function () {
|
|||
Route::group(['prefix' => 'jobs'], function () {
|
||||
Route::get('all', [JobController::class, 'index']);
|
||||
Route::get('byComputer', [JobController::class, 'getByComputerId']);
|
||||
Route::get('byId', [JobController::class, 'getById']);
|
||||
Route::post('create', [JobController::class, 'create']);
|
||||
Route::post('save', [JobController::class, 'update']);
|
||||
Route::post('delete', [JobController::class, 'destroy']);
|
||||
|
|
Loading…
Reference in New Issue