Fix QC Inno
Fix: - app/(application)/admin/donation/category-create.tsx - app/(application)/admin/donation/category-update.tsx - app/(application)/admin/donation/category.tsx - components/_ShareComponent/Admin/TableValue.tsx - screens/Authentication/LoginView.tsx - service/api-admin/api-master-admin.ts ### No Issue
This commit is contained in:
@@ -1,17 +1,56 @@
|
|||||||
import {
|
import {
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { apiAdminMasterDonationCategoryCreate } from "@/service/api-admin/api-master-admin";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Switch } from "react-native-paper";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminDonationCategoryCreate() {
|
export default function AdminDonationCategoryCreate() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [data, setData] = useState({
|
||||||
|
name: "",
|
||||||
|
active: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiAdminMasterDonationCategoryCreate({ data });
|
||||||
|
if (response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text2: "Data berhasil disimpan",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal menyimpan data",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[Error]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom onPress={() => router.back()}>Simpan</ButtonCustom>
|
<ButtonCustom isLoading={loading} onPress={onSubmit}>
|
||||||
|
Simpan
|
||||||
|
</ButtonCustom>
|
||||||
</BoxButtonOnFooter>
|
</BoxButtonOnFooter>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
@@ -20,7 +59,23 @@ export default function AdminDonationCategoryCreate() {
|
|||||||
headerComponent={<AdminBackButtonAntTitle title="Tambah Kategori" />}
|
headerComponent={<AdminBackButtonAntTitle title="Tambah Kategori" />}
|
||||||
footerComponent={buttonSubmit}
|
footerComponent={buttonSubmit}
|
||||||
>
|
>
|
||||||
<TextInputCustom placeholder="Masukkan Kategori" />
|
<TextInputCustom
|
||||||
|
label=""
|
||||||
|
placeholder="Masukkan Kategori"
|
||||||
|
value={data.name}
|
||||||
|
onChangeText={(text) => setData({ ...data, name: text })}
|
||||||
|
/>
|
||||||
|
<StackCustom gap={"sm"}>
|
||||||
|
<TextCustom>Status</TextCustom>
|
||||||
|
<Switch
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
}}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
value={data.active}
|
||||||
|
onValueChange={(value) => setData({ ...data, active: value })}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,21 +1,76 @@
|
|||||||
import {
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import {
|
||||||
|
apiAdminMasterDonationCategoryById,
|
||||||
|
apiAdminMasterDonationCategoryUpdate,
|
||||||
|
} from "@/service/api-admin/api-master-admin";
|
||||||
import { useLocalSearchParams, useRouter } from "expo-router";
|
import { useLocalSearchParams, useRouter } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { Switch } from "react-native-paper";
|
||||||
|
|
||||||
export default function AdminDonationCategoryUpdate() {
|
export default function AdminDonationCategoryUpdate() {
|
||||||
|
const router = useRouter();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [value, setValue] = useState(id);
|
const [value, setValue] = useState(id);
|
||||||
|
|
||||||
const router = useRouter();
|
const [data, setData] = useState<any>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchData = async () => {
|
||||||
|
const response = await apiAdminMasterDonationCategoryById({
|
||||||
|
id: id as any,
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify(response.data, null, 2));
|
||||||
|
|
||||||
|
setData(response.data);
|
||||||
|
};
|
||||||
|
fetchData();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await apiAdminMasterDonationCategoryUpdate({
|
||||||
|
id: id as any,
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify(response.data, null, 2));
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom onPress={() => router.back()}>Update</ButtonCustom>
|
<ButtonCustom
|
||||||
|
disabled={isLoading || data?.name === ""}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Update Data",
|
||||||
|
message: "Apakah anda yakin ingin mengupdate data ini?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressLeft: () => {},
|
||||||
|
onPressRight: () => handlerSubmit(),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCustom>
|
||||||
</BoxButtonOnFooter>
|
</BoxButtonOnFooter>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
@@ -25,10 +80,28 @@ export default function AdminDonationCategoryUpdate() {
|
|||||||
footerComponent={buttonSubmit}
|
footerComponent={buttonSubmit}
|
||||||
>
|
>
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
|
label="Nama Kategori"
|
||||||
placeholder="Masukkan Kategori"
|
placeholder="Masukkan Kategori"
|
||||||
value={value as any}
|
value={data?.name}
|
||||||
onChangeText={setValue}
|
onChangeText={(value) => setData({ ...data, name: value })}
|
||||||
/>
|
/>
|
||||||
|
<StackCustom
|
||||||
|
gap={"sm"}
|
||||||
|
style={{
|
||||||
|
alignContent: "flex-start",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom>Status</TextCustom>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
}}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
value={data?.active}
|
||||||
|
onValueChange={(value) => setData({ ...data, active: value })}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
BaseBox,
|
BadgeCustom,
|
||||||
CenterCustom,
|
BaseBox,
|
||||||
Spacing,
|
CenterCustom,
|
||||||
StackCustom,
|
ClickableCustom,
|
||||||
TextCustom,
|
DividerCustom,
|
||||||
ViewWrapper,
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IconEdit } from "@/components/_Icon";
|
import { IconEdit } from "@/components/_Icon";
|
||||||
import AdminActionIconPlus from "@/components/_ShareComponent/Admin/ActionIconPlus";
|
import AdminActionIconPlus from "@/components/_ShareComponent/Admin/ActionIconPlus";
|
||||||
@@ -14,14 +18,56 @@ import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
|
|||||||
import { GridView_3_3_6 } from "@/components/_ShareComponent/GridView_3_3_6";
|
import { GridView_3_3_6 } from "@/components/_ShareComponent/GridView_3_3_6";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
import { View } from "react-native";
|
import { RefreshControl, View } from "react-native";
|
||||||
import { Divider, Switch } from "react-native-paper";
|
import { Divider, Switch } from "react-native-paper";
|
||||||
import { router } from "expo-router";
|
import { router, useFocusEffect } from "expo-router";
|
||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { apiAdminMasterDonationCategory } from "@/service/api-admin/api-master-admin";
|
||||||
|
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
|
||||||
|
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
|
||||||
|
|
||||||
export default function AdminDonationCategory() {
|
export default function AdminDonationCategory() {
|
||||||
|
const [listData, setListData] = useState<any[]>([]);
|
||||||
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
fetchMaster();
|
||||||
|
}, [])
|
||||||
|
);
|
||||||
|
|
||||||
|
const fetchMaster = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiAdminMasterDonationCategory();
|
||||||
|
if (response.success) {
|
||||||
|
console.log(JSON.stringify(response.data, null, 2));
|
||||||
|
setListData(response.data);
|
||||||
|
} else {
|
||||||
|
setListData([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[Error]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRefresh = async () => {
|
||||||
|
setRefreshing(true);
|
||||||
|
await fetchMaster();
|
||||||
|
setRefreshing(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper headerComponent={<AdminTitlePage title="Donasi" />}>
|
<ViewWrapper
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
|
||||||
|
}
|
||||||
|
headerComponent={<AdminTitlePage title="Donasi" />}
|
||||||
|
>
|
||||||
<AdminComp_BoxTitle
|
<AdminComp_BoxTitle
|
||||||
title="Kategori"
|
title="Kategori"
|
||||||
rightComponent={
|
rightComponent={
|
||||||
@@ -33,81 +79,50 @@ export default function AdminDonationCategory() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BaseBox>
|
<View>
|
||||||
<GridView_3_3_6
|
<Grid>
|
||||||
component1={
|
<Grid.Col style={{paddingLeft: 10}} span={4}>
|
||||||
<TextCustom bold align="center">
|
<TextCustom bold>Status</TextCustom>
|
||||||
Aksi
|
</Grid.Col>
|
||||||
</TextCustom>
|
<Grid.Col span={8}>
|
||||||
}
|
<TextCustom bold>Kategori</TextCustom>
|
||||||
component2={<TextCustom bold>Status</TextCustom>}
|
</Grid.Col>
|
||||||
component3={<TextCustom bold>Kategori</TextCustom>}
|
</Grid>
|
||||||
/>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<Spacing />
|
<Spacing />
|
||||||
|
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
{listData.map((item, index) => (
|
{listData.map((item, index) => (
|
||||||
<View key={index}>
|
<ClickableCustom
|
||||||
<GridView_3_3_6
|
onPress={() => {
|
||||||
component1={
|
router.push(`/admin/donation/category-update?id=${item.id}`);
|
||||||
|
}}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<Grid containerStyle={{ paddingBottom: 10 }}>
|
||||||
|
<Grid.Col
|
||||||
|
span={4}
|
||||||
|
style={{paddingLeft: 10}}
|
||||||
|
>
|
||||||
<CenterCustom>
|
<CenterCustom>
|
||||||
<ActionIcon
|
<BadgeCustom
|
||||||
icon={
|
color={item.active ? MainColor.green : MainColor.red}
|
||||||
<IconEdit size={ICON_SIZE_BUTTON} color="black" />
|
>
|
||||||
}
|
{item.active ? "Aktif" : "Tidak Aktif"}
|
||||||
onPress={() => {
|
</BadgeCustom>
|
||||||
router.push(`/admin/donation/category-update?id=${index}`);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</CenterCustom>
|
</CenterCustom>
|
||||||
}
|
</Grid.Col>
|
||||||
component2={
|
<Grid.Col span={8}>
|
||||||
<Switch
|
<TextCustom bold>{item.name}</TextCustom>
|
||||||
value={true}
|
</Grid.Col>
|
||||||
onValueChange={(item) => {
|
</Grid>
|
||||||
console.log(item);
|
|
||||||
}}
|
|
||||||
color={MainColor.yellow}
|
|
||||||
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
component3={<TextCustom bold>{item.label}</TextCustom>}
|
|
||||||
/>
|
|
||||||
<Spacing height={10} />
|
|
||||||
<Divider />
|
<Divider />
|
||||||
</View>
|
</ClickableCustom>
|
||||||
))}
|
))}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</View>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Kegiatan Sosial",
|
|
||||||
value: "kegiatan_sosial",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Pendidikan",
|
|
||||||
value: "pendidikan",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Kesehatan",
|
|
||||||
value: "kesehatan",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Kebudayaan",
|
|
||||||
value: "kebudayaan",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Bencana Alami",
|
|
||||||
value: "bencana_alami",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Lainnya",
|
|
||||||
value: "lainnya",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
import Grid from "@/components/Grid/GridCustom";
|
import Grid from "@/components/Grid/GridCustom";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { View } from "react-native";
|
import { StyleProp, View, ViewStyle } from "react-native";
|
||||||
import { Divider } from "react-native-paper";
|
import { Divider } from "react-native-paper";
|
||||||
|
|
||||||
export default function AdminTableValue({
|
export default function AdminTableValue({
|
||||||
value1,
|
value1,
|
||||||
value2,
|
value2,
|
||||||
value3,
|
value3,
|
||||||
|
style1,
|
||||||
|
style2,
|
||||||
|
style3,
|
||||||
bottomLine = false,
|
bottomLine = false,
|
||||||
}: {
|
}: {
|
||||||
value1: React.ReactNode;
|
value1: React.ReactNode;
|
||||||
value2: React.ReactNode;
|
value2: React.ReactNode;
|
||||||
value3: React.ReactNode;
|
value3: React.ReactNode;
|
||||||
|
style1?: ViewStyle;
|
||||||
|
style2?: ViewStyle;
|
||||||
|
style3?: ViewStyle;
|
||||||
bottomLine?: boolean;
|
bottomLine?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
@@ -25,6 +31,7 @@ export default function AdminTableValue({
|
|||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
paddingLeft: 10,
|
paddingLeft: 10,
|
||||||
paddingRight: 10,
|
paddingRight: 10,
|
||||||
|
...style1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{value1}
|
{value1}
|
||||||
@@ -36,6 +43,7 @@ export default function AdminTableValue({
|
|||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
paddingLeft: 10,
|
paddingLeft: 10,
|
||||||
paddingRight: 10,
|
paddingRight: 10,
|
||||||
|
...style2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{value2}
|
{value2}
|
||||||
@@ -44,9 +52,10 @@ export default function AdminTableValue({
|
|||||||
span={6}
|
span={6}
|
||||||
style={{
|
style={{
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "flex-start",
|
||||||
paddingLeft: 10,
|
paddingLeft: 10,
|
||||||
paddingRight: 10,
|
paddingRight: 10,
|
||||||
|
...style3,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{value3}
|
{value3}
|
||||||
|
|||||||
@@ -134,10 +134,10 @@ export default function LoginView() {
|
|||||||
|
|
||||||
if (token && token !== "" && isAdmin) {
|
if (token && token !== "" && isAdmin) {
|
||||||
// Akan di aktifkan jika sudah losos review
|
// Akan di aktifkan jika sudah losos review
|
||||||
// return <Redirect href={"/(application)/admin/dashboard"} />;
|
return <Redirect href={"/(application)/admin/dashboard"} />;
|
||||||
|
|
||||||
// Sementara gunakan ini
|
// Sementara gunakan ini
|
||||||
return <Redirect href={"/(application)/(user)/home"} />;
|
// return <Redirect href={"/(application)/(user)/home"} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -167,3 +167,56 @@ export async function apiAdminMasterTypeOfEventUpdate({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================== END EVENT ================== //
|
// ================== END EVENT ================== //
|
||||||
|
|
||||||
|
// ================== START DONATION ================== //
|
||||||
|
|
||||||
|
export async function apiAdminMasterDonationCategory() {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.get(`/mobile/admin/master/donation`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiAdminMasterDonationCategoryById({ id }: { id: string }) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.get(`/mobile/admin/master/donation/${id}`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiAdminMasterDonationCategoryUpdate({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: any;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.put(
|
||||||
|
`/mobile/admin/master/donation/${id}`,
|
||||||
|
{
|
||||||
|
data: data,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiAdminMasterDonationCategoryCreate({ data }: { data: any }) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.post(`/mobile/admin/master/donation`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== END DONATION ================== //
|
||||||
Reference in New Issue
Block a user