chore: initial import for test contour
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/* global FormData */
|
||||
|
||||
import { API } from './apiSlice';
|
||||
|
||||
const authHeader = () => {
|
||||
const token = localStorage.getItem('token');
|
||||
return token ? { Authorization: `Bearer ${token}` } : {};
|
||||
};
|
||||
|
||||
export const certificateApi = API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
getCertificate: build.query({
|
||||
query: ({id}) => {
|
||||
return {
|
||||
url: `/specialist-docs/${id}`,
|
||||
method: 'GET',
|
||||
// headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
createCertificate: build.mutation({
|
||||
query: ({specialistId, data}) => {
|
||||
return {
|
||||
url: `/specialist/${specialistId}/specialist-docs/create`,
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
},
|
||||
}),
|
||||
updateCertificate: build.mutation({
|
||||
query: ({specialistId, id, data}) => {
|
||||
return {
|
||||
url: `/specialist/${specialistId}/specialist-docs/${id}`,
|
||||
method: 'PUT',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
},
|
||||
}),
|
||||
uploadSertificatePicture: build.mutation({
|
||||
query: ({ id, file }) => {
|
||||
const formData = new FormData();
|
||||
formData.append('picture', file);
|
||||
return {
|
||||
url: `/specialist-docs/picture/${id}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...authHeader(),
|
||||
},
|
||||
body: formData,
|
||||
};
|
||||
},
|
||||
}),
|
||||
deleteCertificate: build.mutation({
|
||||
query: ({id}) => {
|
||||
return {
|
||||
url: `/specialist-docs/${id}`,
|
||||
method: 'DELETE',
|
||||
headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetCertificateQuery,
|
||||
useCreateCertificateMutation,
|
||||
useUpdateCertificateMutation,
|
||||
useUploadSertificatePictureMutation,
|
||||
useDeleteCertificateMutation,
|
||||
} = certificateApi;
|
||||
@@ -0,0 +1,117 @@
|
||||
import { API, authHeader } from './apiSlice'
|
||||
import { CONTENT_RESOURCES } from '../config/contentResources'
|
||||
|
||||
const buildListQuery = (basePath, { usesLimit = false } = {}) =>
|
||||
({ search = '', page = 1, perPage = 20 } = {}) => {
|
||||
let queryString = `?page=${page}`
|
||||
if (usesLimit) {
|
||||
queryString += `&limit=${perPage}`
|
||||
} else {
|
||||
queryString += `&perPage=${perPage}`
|
||||
}
|
||||
if (search) {
|
||||
queryString += `&search=${encodeURIComponent(search)}`
|
||||
}
|
||||
return {
|
||||
url: `${basePath}/list${queryString}`,
|
||||
}
|
||||
}
|
||||
|
||||
const injectResource = (resourceKey) => {
|
||||
const { basePath, listUsesLimit } = CONTENT_RESOURCES[resourceKey]
|
||||
const cap = resourceKey
|
||||
.split('-')
|
||||
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
||||
.join('')
|
||||
|
||||
return API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
[`get${cap}List`]: build.query({
|
||||
query: buildListQuery(basePath, { usesLimit: listUsesLimit }),
|
||||
refetchOnMountOrArgChange: true,
|
||||
keepUnusedDataFor: 0,
|
||||
}),
|
||||
[`get${cap}Item`]: build.query({
|
||||
query: (id) => ({
|
||||
url: `${basePath}/${id}`,
|
||||
}),
|
||||
}),
|
||||
[`create${cap}`]: build.mutation({
|
||||
query: (data) => ({
|
||||
url: `${basePath}/create`,
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
}),
|
||||
[`update${cap}`]: build.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `${basePath}/${id}`,
|
||||
method: 'PUT',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
}),
|
||||
[`delete${cap}`]: build.mutation({
|
||||
query: (id) => ({
|
||||
url: `${basePath}/${id}`,
|
||||
method: 'DELETE',
|
||||
headers: authHeader(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
overrideExisting: false,
|
||||
})
|
||||
}
|
||||
|
||||
const newsApi = injectResource('news')
|
||||
const promoApi = injectResource('promo')
|
||||
const diseaseApi = injectResource('disease')
|
||||
const medicalCenterApi = injectResource('medical-center')
|
||||
const articleApi = injectResource('article')
|
||||
const siteServicesApi = injectResource('site-services')
|
||||
|
||||
export const contentHooks = {
|
||||
news: {
|
||||
useListQuery: newsApi.useGetNewsListQuery,
|
||||
useItemQuery: newsApi.useGetNewsItemQuery,
|
||||
useCreateMutation: newsApi.useCreateNewsMutation,
|
||||
useUpdateMutation: newsApi.useUpdateNewsMutation,
|
||||
useDeleteMutation: newsApi.useDeleteNewsMutation,
|
||||
},
|
||||
promo: {
|
||||
useListQuery: promoApi.useGetPromoListQuery,
|
||||
useItemQuery: promoApi.useGetPromoItemQuery,
|
||||
useCreateMutation: promoApi.useCreatePromoMutation,
|
||||
useUpdateMutation: promoApi.useUpdatePromoMutation,
|
||||
useDeleteMutation: promoApi.useDeletePromoMutation,
|
||||
},
|
||||
disease: {
|
||||
useListQuery: diseaseApi.useGetDiseaseListQuery,
|
||||
useItemQuery: diseaseApi.useGetDiseaseItemQuery,
|
||||
useCreateMutation: diseaseApi.useCreateDiseaseMutation,
|
||||
useUpdateMutation: diseaseApi.useUpdateDiseaseMutation,
|
||||
useDeleteMutation: diseaseApi.useDeleteDiseaseMutation,
|
||||
},
|
||||
'medical-center': {
|
||||
useListQuery: medicalCenterApi.useGetMedicalCenterListQuery,
|
||||
useItemQuery: medicalCenterApi.useGetMedicalCenterItemQuery,
|
||||
useCreateMutation: medicalCenterApi.useCreateMedicalCenterMutation,
|
||||
useUpdateMutation: medicalCenterApi.useUpdateMedicalCenterMutation,
|
||||
useDeleteMutation: medicalCenterApi.useDeleteMedicalCenterMutation,
|
||||
},
|
||||
article: {
|
||||
useListQuery: articleApi.useGetArticleListQuery,
|
||||
useItemQuery: articleApi.useGetArticleItemQuery,
|
||||
useCreateMutation: articleApi.useCreateArticleMutation,
|
||||
useUpdateMutation: articleApi.useUpdateArticleMutation,
|
||||
useDeleteMutation: articleApi.useDeleteArticleMutation,
|
||||
},
|
||||
'site-services': {
|
||||
useListQuery: siteServicesApi.useGetSiteServicesListQuery,
|
||||
useItemQuery: siteServicesApi.useGetSiteServicesItemQuery,
|
||||
useCreateMutation: siteServicesApi.useCreateSiteServicesMutation,
|
||||
useUpdateMutation: siteServicesApi.useUpdateSiteServicesMutation,
|
||||
useDeleteMutation: siteServicesApi.useDeleteSiteServicesMutation,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { API, authHeader } from './apiSlice'
|
||||
/*
|
||||
const authHeader = () => {
|
||||
const token = localStorage.getItem('token')
|
||||
return token ? { Authorization: `Bearer ${token}` } : {}
|
||||
}
|
||||
*/
|
||||
export const departmentApi = API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
getDepartments: build.query({
|
||||
query: () => '/department/list',
|
||||
}),
|
||||
updateDepartments: build.mutation({
|
||||
query: ({ departmentId, data }) => {
|
||||
return ({
|
||||
url: `/department/${departmentId}`,
|
||||
method: 'PUT',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
})},
|
||||
}),
|
||||
createDepartments: build.mutation({
|
||||
query: ({ data }) => {
|
||||
return ({
|
||||
url: `/department/create`,
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
})},
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const {
|
||||
useGetDepartmentsQuery,
|
||||
useUpdateDepartmentsMutation,
|
||||
useCreateDepartmentsMutation,
|
||||
} = departmentApi
|
||||
@@ -0,0 +1,53 @@
|
||||
/* global FormData */
|
||||
|
||||
import { API, authHeader } from './apiSlice'
|
||||
|
||||
export const filialApi = API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
getFilials: build.query({
|
||||
query: () => '/filial/list',
|
||||
refetchOnMountOrArgChange: true,
|
||||
keepUnusedDataFor: 0,
|
||||
}),
|
||||
updateFilial: build.mutation({
|
||||
query: ({ filialId, data }) => {
|
||||
return ({
|
||||
url: `/filial/${filialId}`,
|
||||
method: 'PUT',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
})},
|
||||
}),
|
||||
uploadFilialPicture: build.mutation({
|
||||
query: ({ id, file }) => {
|
||||
const formData = new FormData();
|
||||
formData.append('picture', file);
|
||||
return {
|
||||
url: `/filial/picture/${id}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...authHeader(),
|
||||
},
|
||||
body: formData,
|
||||
};
|
||||
},
|
||||
}),
|
||||
createFilial: build.mutation({
|
||||
query: ({ data }) => {
|
||||
return ({
|
||||
url: `/filial/create`,
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const {
|
||||
useGetFilialsQuery,
|
||||
useUpdateFilialMutation,
|
||||
useUploadFilialPictureMutation,
|
||||
useCreateFilialMutation,
|
||||
} = filialApi
|
||||
@@ -0,0 +1,22 @@
|
||||
import { API } from './apiSlice';
|
||||
|
||||
const authHeader = () => {
|
||||
const token = localStorage.getItem('token');
|
||||
return token ? { Authorization: `Bearer ${token}` } : {};
|
||||
};
|
||||
|
||||
export const iDoctorApi = API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
getIDoctors: build.query({
|
||||
query: ({ value = '', type, page = 1 }) => {
|
||||
return {
|
||||
url: `/idoctor/list?page=${page}&perPage=100${ type ? ( type === 'search' ? `&search=${value}` : ( type === 'dcode' ? `&dcode=${value}` : '' )) : '' }`,
|
||||
headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
overrideExisting: false,
|
||||
});
|
||||
|
||||
export const { useGetIDoctorsQuery } = iDoctorApi;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { API } from './apiSlice';
|
||||
|
||||
const authHeader = () => {
|
||||
const token = localStorage.getItem('token');
|
||||
return token ? { Authorization: `Bearer ${token}` } : {};
|
||||
};
|
||||
|
||||
export const KodoperApi = API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
getKodopers: build.query({
|
||||
query: ({value, filialId, page}) => {
|
||||
const querySearch = value ? `search=${value}` : '';
|
||||
let queryFilial = '';
|
||||
if (filialId) {
|
||||
if (filialId >= 0) {
|
||||
queryFilial = `filial=${filialId}`
|
||||
}
|
||||
}
|
||||
const queryPage = page ? `page=${page}` : '';
|
||||
return {
|
||||
url: `/pricelist/list?${queryFilial ? `${querySearch}&` : querySearch}${queryPage ? `${queryFilial}&` : queryFilial}${queryPage}`,
|
||||
headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
overrideExisting: false,
|
||||
});
|
||||
|
||||
export const { useGetKodopersQuery } = KodoperApi;
|
||||
@@ -0,0 +1,51 @@
|
||||
import { API } from './apiSlice'
|
||||
|
||||
const authHeader = () => {
|
||||
const token = localStorage.getItem('token')
|
||||
return token ? { Authorization: `Bearer ${token}` } : {}
|
||||
}
|
||||
|
||||
export const locationApi = API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
createLocation: build.mutation({
|
||||
query: ({ specialistId, data }) => ({
|
||||
url: `/specialist/${specialistId}/location/create`,
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
invalidatesTags: ['Specialist'],
|
||||
}),
|
||||
updateLocation: build.mutation({
|
||||
query: ({ specialistId, locationId, data }) => {
|
||||
return ({
|
||||
url: `/specialist/${specialistId}/location/${locationId}`,
|
||||
method: 'PUT',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
})},
|
||||
}),
|
||||
deleteLocation: build.mutation({
|
||||
query: (locationId) => ({
|
||||
url: `/location/${locationId}`,
|
||||
method: 'DELETE',
|
||||
headers: authHeader(),
|
||||
}),
|
||||
}),
|
||||
getEmptyLocations: build.query({
|
||||
query: () => {
|
||||
return {
|
||||
url: `/locations/empty`,
|
||||
headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const {
|
||||
useCreateLocationMutation,
|
||||
useUpdateLocationMutation,
|
||||
useDeleteLocationMutation,
|
||||
useGetEmptyLocationsQuery,
|
||||
} = locationApi
|
||||
@@ -0,0 +1,44 @@
|
||||
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
|
||||
import { API_BASE_URL } from '@/config/api'
|
||||
|
||||
export const authHeader = () => {
|
||||
const token = localStorage.getItem('token')
|
||||
return token ? { Authorization: `Bearer ${token}` } : {}
|
||||
}
|
||||
|
||||
export const API = createApi({
|
||||
reducerPath: 'API',
|
||||
baseQuery: fetchBaseQuery({
|
||||
baseUrl: API_BASE_URL,
|
||||
credentials: 'include',
|
||||
}),
|
||||
endpoints: (builder) => ({
|
||||
login: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: '/user/login',
|
||||
method: 'POST',
|
||||
body: data,
|
||||
}),
|
||||
async onQueryStarted(arg, { queryFulfilled }) {
|
||||
try {
|
||||
const { data } = await queryFulfilled
|
||||
console.log(data)
|
||||
localStorage.setItem('token', data.token)
|
||||
localStorage.setItem('admSovamedUserUID', data.user.uid)
|
||||
localStorage.setItem('admSovamedUserRegionId', data.user.regionId)
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
logout: builder.mutation({
|
||||
async queryFn(_arg, _api, _extraOptions, _baseQuery) {
|
||||
localStorage.removeItem('token')
|
||||
return { data: undefined }
|
||||
},
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const { useLoginMutation, useLogoutMutation } = API;
|
||||
@@ -0,0 +1,119 @@
|
||||
/* global FormData */
|
||||
|
||||
import { API } from './apiSlice'
|
||||
|
||||
const authHeader = () => {
|
||||
const token = localStorage.getItem('token')
|
||||
return token ? { Authorization: `Bearer ${token}` } : {}
|
||||
}
|
||||
|
||||
export const specialistApi = API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
getSpecialist: build.query({
|
||||
query: (specialistId) => ({
|
||||
url: `/specialist/${specialistId}`,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
...authHeader(),
|
||||
},
|
||||
}),
|
||||
refetchOnMountOrArgChange: true,
|
||||
keepUnusedDataFor: 0,
|
||||
}),
|
||||
getSpecialists: build.query({
|
||||
query: (regionId) => {
|
||||
return regionId === 'all'
|
||||
? '/specialist/list'
|
||||
: `/specialist/list?regionId=${regionId}`
|
||||
},
|
||||
refetchOnMountOrArgChange: true,
|
||||
keepUnusedDataFor: 0,
|
||||
}),
|
||||
getSpecialistsList: build.query({
|
||||
query: ({ regionId = '', search = '', page = '' }) => {
|
||||
let queryString = '';
|
||||
|
||||
if (regionId) queryString += `regionId=${regionId}`
|
||||
|
||||
if (search) {
|
||||
if (regionId) queryString += '&'
|
||||
queryString += `search=${search}`
|
||||
}
|
||||
|
||||
if (page) {
|
||||
if (search || regionId) queryString += '&';
|
||||
queryString += `page=${page}`
|
||||
}
|
||||
|
||||
return `/specialist/list${queryString ? `?${queryString}` : ''}`
|
||||
},
|
||||
refetchOnMountOrArgChange: true,
|
||||
keepUnusedDataFor: 0,
|
||||
}),
|
||||
uploadSpecialistPicture: build.mutation({
|
||||
query: ({ id, file }) => {
|
||||
console.log(file)
|
||||
const formData = new FormData();
|
||||
formData.append('previewPicture', file);
|
||||
console.log([...formData.entries()])
|
||||
return {
|
||||
url: `/specialist/picture/${id}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...authHeader(),
|
||||
},
|
||||
body: formData,
|
||||
};
|
||||
},
|
||||
}),
|
||||
createSpecialist: build.mutation({
|
||||
query: ({ data }) => ({
|
||||
url: '/specialist/create',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...authHeader(),
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
invalidatesTags: ['Specialist'],
|
||||
}),
|
||||
updateSpecialist: build.mutation({
|
||||
query: ({ specialistId, data }) => {
|
||||
return ({
|
||||
url: `/specialist/${specialistId}`,
|
||||
method: 'PUT',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
invalidatesTags: (result, error, { specialistId }) => [
|
||||
{ type: 'Specialist', id: specialistId },
|
||||
'Specialist',
|
||||
]
|
||||
}),
|
||||
deleteSpecialist: build.mutation({
|
||||
query: (specialistId) => ({
|
||||
url: `/specialist/${specialistId}`,
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
...authHeader(),
|
||||
},
|
||||
}),
|
||||
invalidatesTags: (result, error, id) => [
|
||||
{ type: 'Specialist', id },
|
||||
'Specialist',
|
||||
],
|
||||
}),
|
||||
}),
|
||||
overrideExisting: false,
|
||||
})
|
||||
|
||||
export const {
|
||||
useGetSpecialistQuery,
|
||||
useGetSpecialistsQuery,
|
||||
useGetSpecialistsListQuery,
|
||||
useUploadSpecialistPictureMutation,
|
||||
useCreateSpecialistMutation,
|
||||
useUpdateSpecialistMutation,
|
||||
useDeleteSpecialistMutation,
|
||||
} = specialistApi
|
||||
@@ -0,0 +1,102 @@
|
||||
/* global FormData */
|
||||
|
||||
import { API, authHeader } from './apiSlice';
|
||||
|
||||
export const stockApi = API.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
getStocks: build.query({
|
||||
query: ({ search = '', page = '' }) => {
|
||||
let queryString = '';
|
||||
if (search || page) queryString += '?'
|
||||
if (search) queryString += `search=${search}`
|
||||
if (search && page) queryString += `&`
|
||||
if (page) queryString += `page=${page}`
|
||||
return {
|
||||
url: `stock/list${queryString}`,
|
||||
//headers: authHeader(),
|
||||
};
|
||||
},
|
||||
refetchOnMountOrArgChange: true,
|
||||
keepUnusedDataFor: 0,
|
||||
}),
|
||||
getStock: build.query({
|
||||
query: ({ stockId }) => {
|
||||
console.log(stockId)
|
||||
return {
|
||||
url: `/stock/${stockId}`,
|
||||
//headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
createStock: build.mutation({
|
||||
query: ({ data }) => {
|
||||
return {
|
||||
url: `/stock/create`,
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
},
|
||||
}),
|
||||
updateStock: build.mutation({
|
||||
query: ({ stockId, data }) => {
|
||||
return {
|
||||
url: `/stock/${stockId}`,
|
||||
method: 'PUT',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
},
|
||||
}),
|
||||
uploadStockPicture: build.mutation({
|
||||
query: ({ id, file }) => {
|
||||
const formData = new FormData();
|
||||
formData.append('picture', file);
|
||||
return {
|
||||
url: `/stock/picture/${id}`,
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
body: formData,
|
||||
};
|
||||
},
|
||||
}),
|
||||
deleteStock: build.mutation({
|
||||
query: ({ stockId }) => {
|
||||
return {
|
||||
url: `/stock/${stockId}`,
|
||||
method: 'DELETE',
|
||||
headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
addSpecialist: build.mutation({
|
||||
query: ({ stockId, specialistId }) => {
|
||||
return {
|
||||
url: `/stock/${stockId}/specialist/${specialistId}`,
|
||||
method: 'PUT',
|
||||
headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
removeSpecialist: build.mutation({
|
||||
query: ({ stockId, specialistId }) => {
|
||||
return {
|
||||
url: `/stock/${stockId}/specialist/${specialistId}`,
|
||||
method: 'DELETE',
|
||||
headers: authHeader(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetStockQuery,
|
||||
useGetStocksQuery,
|
||||
useCreateStockMutation,
|
||||
useUpdateStockMutation,
|
||||
useUploadStockPictureMutation,
|
||||
useDeleteStockMutation,
|
||||
useAddSpecialistMutation,
|
||||
useRemoveSpecialistMutation,
|
||||
} = stockApi;
|
||||
Reference in New Issue
Block a user