Commit 45a9945d authored by Soo Hyun Kim's avatar Soo Hyun Kim
Browse files

0803 세부카테고리 추가수정삭제 및 아코디언

parent 139ee982
......@@ -4,20 +4,16 @@ import editApi from './db/editOption.api';
import AntDesign from 'react-native-vector-icons/AntDesign';
import InputBox from './components/InputBox';
import StyledButton from './components/StyledButton';
import Accordion from './components/Accordion';
import Accordion, { AccordionItem } from './components/Accordion';
const INIT_OPTION = { id: 0, value: '' }
const TEST_OPTION = { id: 15, value: 'testtest' }
const TEST_SUB = [{
id: 1, value: 'test1',
},
{
id: 2, value: 'test2'
}]
const INIT_SUBOPTION = { id: 0, value: '', foreign_id: 0 }
const EditOption = ({ route }) => {
console.log('catEdit: type_id ', route.params)
const type = route.params ? 'category' : 'asset'
const type_id = route.params
const [options, setOptions] = useState([])
const [option, setOption] = useState(INIT_OPTION)
......@@ -28,122 +24,86 @@ const EditOption = ({ route }) => {
const [loading, setLoading] = useState(false);
useEffect(() => {
if (type_id > 0) {
loadCat()
} else {
loadAsset()
}
loadOptions()
}, [])
const loadCat = async () => {
const loadOptions = async () => {
try {
const catArray = await editApi.selectCategories(type_id)
setOptions(catArray)
let optionArray = []
if (type === 'asset') {
optionArray = await editApi.selectAssetsType()
} else if (type === 'category') {
optionArray = await editApi.selectCategories(type_id)
}
setOptions(optionArray)
} catch (error) {
}
}
const loadAsset = async () => {
const handleUpdate = async () => {
try {
const assetArray = await editApi.selectAssetsType()
setOptions(assetArray)
if (type === 'asset') {
const res = await editApi.updateOption('assets_type', { id: option.id, name: 'assets', value: option.value })
console.log(res)
} else if (type === 'category') {
if (option.foreign_id && option.foreign_id > 0) {
const res = await editApi.updateOption('subcategories', { id: option.id, name: 'subcategory', value: option.value })
return console.log(res)
}
const res = await editApi.updateOption('categories', { id: option.id, name: 'category', value: option.value })
console.log(res)
}
} catch (error) {
}
}
const handleUpdate = () => {
if (type_id > 0) {
updateCat()
} else {
updateAsset()
}
}
const updateAsset = async () => {
try {
const res = await editApi.updateOption('assets_type', { id: option.id, name: 'assets', value: option.value })
console.log(res)
loadAsset()
} finally {
loadOptions()
modalClose()
} catch (error) {
}
}
const updateCat = async () => {
const handleDelete = async (item) => {
try {
const res = await editApi.updateOption('categories', { id: option.id, name: 'category', value: option.value })
console.log(res)
loadCat()
modalClose()
if (type === 'asset') {
const res = await editApi.deleteOption('assets_type', { id: item.id, name: 'assets' })
console.log(res)
} else if (type === 'category') {
if (item.foreign_id && item.foreign_id > 0) {
const res = await editApi.deleteOption('subcategories', { id: item.id, name: 'subcategory'})
return console.log(res)
}
const res = await editApi.deleteOption('categories', { id: item.id, name: 'category' })
console.log(res)
}
} catch (error) {
} finally {
loadOptions()
}
}
const handleDelete = (item) => {
if (type_id > 0) {
deleteCat(item)
} else {
deleteAsset(item)
}
}
const deleteAsset = async (item) => {
const handleAdd = async () => {
try {
const res = await editApi.deleteOption('assets_type', { id: item.id, name: 'assets' })
console.log(res)
loadAsset()
modalClose()
if (type === 'asset') {
const res = await editApi.addOption('assets_type', { name: 'assets', value: option.value })
console.log(res)
} else if (type === 'category') {
if (option.foreign_id && option.foreign_id > 0) {
const res = await editApi.addOption('subcategories', { name: 'subcategory', value: option.value, foreign_name: 'category', foreign_id: option.foreign_id })
return console.log(res)
}
const res = await editApi.addOption('categories', { name: 'category', value: option.value, foreign_name: 'type', foreign_id: type_id })
console.log(res)
}
} catch (error) {
}
}
const deleteCat = async (item) => {
try {
const res = await editApi.deleteOption('categories', { id: item.id, name: 'category' })
console.log(res)
loadCat()
} finally {
loadOptions()
modalClose()
} catch (error) {
}
}
const handleAdd = () => {
if (type_id > 0) {
addCat()
} else {
addAsset()
}
}
const addAsset = async () => {
try {
const res = await editApi.addOption('assets_type', { name: 'assets', value: option.value })
console.log(res)
loadAsset()
modalClose()
} catch (error) {
}
}
const addCat = async () => {
try {
const res = await editApi.addOption('categories', { name: 'category', value: option.value, foreign_name: 'type', foreign_id: type_id })
console.log(res)
loadCat()
modalClose()
} catch (error) {
}
}
const renderOptionItem = ({ item }) => (
const renderAssetItem = ({ item }) => (
<View style={[style.flexRow, style.catBox]}>
<View style={style.flexRow}>
{item.deletable && <AntDesign name='minuscircle' style={style.cancelIcon} onPress={() => { handleDelete(item) }} />}
......@@ -151,36 +111,56 @@ const EditOption = ({ route }) => {
{item.value}
</Text>
</View>
<View style={[style.flexRow, style.flexCenter]}>
{item.deletable && <AntDesign name='edit' style={style.icon} onPress={() => { setOption(item); setModalOpen(true) }} />}
<AntDesign name='right' style={style.rightIcon} onPress={() => console.log('서브 카테고리 더보기')} />
</View>
{item.deletable && <AntDesign name='edit' style={style.icon} onPress={() => { setOption(item); setModalOpen(true) }} />}
</View>
);
const renderCatItem = ({ item }) => (
<Accordion
title={item.value}
left={item.deletable && <AntDesign name='closecircle' style={style.cancelIcon} onPress={() => { handleDelete(item) }} />}
right={item.deletable && <AntDesign name='edit' style={style.icon} onPress={() => { setOption(item); setModalOpen(true) }} />}
titleStyle={style.optionText}
backgroundColor='lightgray'
>
{item.subOptions.length !== 0 &&
<FlatList
data={item.subOptions}
renderItem={({ item }) => (
<AccordionItem
title={item.value}
left={<AntDesign name='closecircle' style={style.cancelIcon} onPress={() => { handleDelete(item) }} />}
right={<AntDesign name='edit' style={style.icon} onPress={() => { setOption(item); setModalOpen(true) }} />}
titleStyle={style.optionText}
backgroundColor='#b0b0b0'
marginLeft={30}
/>
)}
keyExtractor={item => item.id.toString()}
/>
}
<Pressable
style={[style.flexRow, { backgroundColor: "#b0b0b0", paddingVertical: 10 }]}
onPress={() => {
setOption({...INIT_SUBOPTION, ['foreign_id']: item.id});
setModalOpen(true)
}}
>
<AntDesign name='plus' style={[style.addIcon, { marginLeft: 35 }]} />
<Text style={style.optionText} >추가하기</Text>
</Pressable>
</Accordion>
);
return (
<>
{console.log(option)}
<View>
<FlatList
data={options}
renderItem={renderOptionItem}
renderItem={type === 'asset' ? renderAssetItem : renderCatItem}
keyExtractor={item => item.id.toString()}
/>
<Accordion subItems={TEST_SUB}>
<View style={[style.flexRow, style.catBox]}>
<View style={style.flexRow}>
<AntDesign name='minuscircle' style={style.cancelIcon} onPress={() => { handleDelete({ TEST_OPTION }) }} />
<Text style={style.optionText} >
{TEST_OPTION.value}
</Text>
</View>
<View style={[style.flexRow, style.flexCenter]}>
<AntDesign name='edit' style={style.icon} onPress={() => { setOption(TEST_OPTION); setModalOpen(true) }} />
<AntDesign name='right' style={style.rightIcon} onPress={() => console.log('서브 카테고리 더보기')} />
</View>
</View>
</Accordion>
<Pressable style={style.addButton} onPress={() => setModalOpen(true)}>
<AntDesign name='plus' style={style.icon} />
<Text style={style.optionText} >추가하기</Text>
......@@ -246,9 +226,14 @@ const style = StyleSheet.create({
fontSize: 30,
color: 'black',
},
addIcon: {
marginHorizontal: 5,
fontSize: 25,
color: 'black',
},
cancelIcon: {
marginHorizontal: 5,
fontSize: 30,
fontSize: 25,
color: 'red',
},
rightIcon: {
......
import React, { useEffect, useRef, useState } from 'react';
import { Animated, Text, View, StyleSheet, TouchableOpacity, FlatList } from 'react-native';
const renderOptionItem = ({ item }) => (
<View style={[style.flexRow, style.catBox]}>
<View style={style.flexRow}>
{/* { item.deletable && <AntDesign name='minuscircle' style={style.cancelIcon} onPress={() => { handleDelete(item) }} />} */}
<Text style={style.optionText} >
{item.value}
</Text>
</View>
{/* <View style={[style.flexRow, style.flexCenter]}>
{ item.deletable && <AntDesign name='edit' style={style.icon} onPress={() => { setOption(item); setModalOpen(true) }} /> }
<AntDesign name='right' style={style.rightIcon} onPress={() => console.log('서브 카테고리 더보기')}/>
</View> */}
</View>
);
import React, { useState } from 'react';
import { Animated, Text, View, StyleSheet, Pressable } from 'react-native';
import AntDesign from 'react-native-vector-icons/AntDesign';
const Accordion = ({
item,
subItems,
children
title,
left,
right,
children,
titleStyle = style.text,
backgroundColor = 'lightgray',
}) => {
let layoutHeight = 0;
const [bodyMounted, setBodyMounted] = useState(false);
const [bodyHeight, setBodyHeight] = useState(0);
let dropDownAnimValueList = useRef(new Animated.Value(0)).current;
const handleBodyLayout = (e) => {
if (bodyMounted) return;
console.log(e.nativeEvent.layout)
const { height } = e.nativeEvent.layout;
layoutHeight = height;
setBodyMounted(true);
setBodyHeight(height);
}
const [open, setOpen] = useState(false);
// const openList = () => {
// Animated.timing(dropDownAnimValueList, {
// toValue: 0,
// duration: 500,
// useNativeDriver: true,
// })
// }
// const closeList = () => {
// Animated.timing(dropDownAnimValueList, {
// toValue: -bodyHeight,
// duration: 500,
// useNativeDriver: true,
// })
// }
useEffect(() => {
if (bodyMounted) dropDownAnimValueList.setValue(open ? -layoutHeight : 0);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [bodyMounted]);
useEffect(() => {
// if (shouldAnimate) {
// if (!opened) {
// Animated.timing(dropDownAnimValueList, {
// toValue: 0,
// duration: animDuration || 300,
// useNativeDriver: true,
// }).start();
// return;
// }
// Animated.timing(dropDownAnimValueList, {
// toValue: -bodyHeight,
// duration: animDuration || 300,
// useNativeDriver: true,
// }).start();
// } else {
const targetValue = open ? -bodyHeight : 0;
dropDownAnimValueList.setValue(targetValue);
// }
// if (open) dropDownAnimValueList.setValue(open ? -layoutHeight : 0);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open]);
const [opened, setOpened] = useState(false);
console.log(open)
const handleOpen = () => { setOpened(!opened) };
return (
<Animated.View style={[
{
overflow: 'hidden',
transform: [{
translateY: 0,
}],
},
]}>
<View style={[style.boxContainer]}>
<TouchableOpacity onPress={() => { setOpen(!open) }}>
{children}
</TouchableOpacity>
<View>
<View>
<Pressable
style={[style.flexRow, style.catBox, { backgroundColor: backgroundColor }]}
onPress={handleOpen}
>
<View style={[style.flexRow, style.flexCenter]}>
{left ? left : null}
<Text style={titleStyle}>
{title}
</Text>
</View>
<View style={[style.flexRow, style.flexCenter]}>
{right ? right : null}
<AntDesign
name={opened ? 'caretup' : 'caretdown'}
color='black'
size={24}
style={style.rightIcon}
/>
</View>
</Pressable>
</View>
<Animated.View style={{
height: !bodyMounted ? undefined : bodyHeight,
transform: [
{
translateY: dropDownAnimValueList,
},
],
}}
onLayout={handleBodyLayout}>
<FlatList
data={subItems}
renderItem={renderOptionItem}
keyExtractor={item => item.id.toString()}
/>
</Animated.View>
</Animated.View>
{opened ?
children
: null}
</View>
)
}
const Accordion
};
export const AccordionItem = ({
title,
left,
right,
titleStyle = style.text,
backgroundColor = 'lightgray',
marginLeft = 20,
}) => {
return (
<View style={[style.flexRow, style.flexCenter, style.catBox, { backgroundColor: backgroundColor }]}>
<View style={[style.flexRow, style.flexCenter, { marginLeft: marginLeft }]}>
{left ? left : null}
<Text style={titleStyle}>
{title}
</Text>
</View>
{right ? right : null}
</View>
);
};
const style = StyleSheet.create({
boxContainer: {
width: '100%',
position: 'relative',
},
flexRow: {
flexDirection: 'row',
},
......@@ -139,35 +78,16 @@ const style = StyleSheet.create({
catBox: {
justifyContent: 'space-between',
paddingVertical: 10,
backgroundColor: 'lightgray',
},
zIndex: {
position: 'absolute',
zIndex: 15,
elevation: 1000,
},
icon: {
marginHorizontal: 5,
fontSize: 30,
color: 'black',
},
cancelIcon: {
marginHorizontal: 5,
fontSize: 30,
color: 'red',
},
rightIcon: {
marginHorizontal: 5,
fontSize: 20,
color: 'black',
},
optionText: {
text: {
fontSize: 20,
marginHorizontal: 10,
},
items: {
overflow: "hidden"
}
})
export default Accordion
\ No newline at end of file
......@@ -12,20 +12,50 @@ const selectCategories = async (type_id) => {
return new Promise((resolve, reject) => {
db.transaction(async (tx) => {
console.log("카테고리 부르기");
const [txn, results] = await tx.executeSql(`SELECT * FROM categories WHERE type_id=${type_id}`);
const [txn, results] = await tx.executeSql(
`select cat.category_id, category_name, subcat_id, subcat_name from categories as cat
left join (
SELECT category_id,
group_concat(subcategory_id, '|') as subcat_id,
group_concat(subcategory_name, '|') as subcat_name
from subcategories group by category_id
) as subcat
on cat.category_id=subcat.category_id
where cat.type_id='${type_id}'`
);
console.log('item length', results.rows.length);
const temp = [];
for (let i = 0; i < results.rows.length; i++) {
const tempId = results.rows.item(i).category_id;
const tempName = results.rows.item(i).category_name;
if (tempId < CAT_LIMIT_ID) {
temp.push({ id: tempId, value: tempName, deletable: false });
} else {
temp.push({ id: tempId, value: tempName, deletable: true });
let deletable = (tempId < CAT_LIMIT_ID) ? false : true;
const tempSubOptions = [];
if (results.rows.item(i).subcat_id) {
const tempSubId = results.rows.item(i).subcat_id.split('|');
const tempSubValue = results.rows.item(i).subcat_name.split('|');
for (let i = 0; i < tempSubId.length; i++) {
tempSubOptions.push({ id: tempSubId[i], value: tempSubValue[i], foreign_id: tempId });
}
}
temp.push({ id: tempId, value: tempName, deletable: deletable, subOptions: tempSubOptions });
}
console.log(temp)
resolve(temp);
// console.log("카테고리 부르기");
// const [txn, results] = await tx.executeSql(`SELECT * FROM categories WHERE type_id=${type_id}`);
// console.log('item length', results.rows.length);
// const temp = [];
// for (let i = 0; i < results.rows.length; i++) {
// const tempId = results.rows.item(i).category_id;
// const tempName = results.rows.item(i).category_name;
// if (tempId < CAT_LIMIT_ID) {
// temp.push({ id: tempId, value: tempName, deletable: false });
// } else {
// temp.push({ id: tempId, value: tempName, deletable: true });
// }
// }
// console.log(temp)
// resolve(temp);
})
})
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment