From d299484a98f6546fd543a9e0ed9584cd54f323ee Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Tue, 12 May 2026 10:34:31 +0800 Subject: [PATCH] refactor: pecah lib/api.ts dan constants/Styles.ts per domain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - lib/api.ts (879 baris) → 13 file di lib/api/ per domain - constants/Styles.ts (1.275 baris) → 10 file di constants/styles/ per domain - tambah docs/FILE-HEALTH.md dan referensinya ke CLAUDE.md - kedua file lama tetap sebagai re-export — zero breaking changes --- CLAUDE.md | 4 + constants/Styles.ts | 1277 +------------------------ constants/styles/border.styles.ts | 17 + constants/styles/button.styles.ts | 44 + constants/styles/card.styles.ts | 159 +++ constants/styles/component.styles.ts | 135 +++ constants/styles/header.styles.ts | 23 + constants/styles/index.ts | 26 + constants/styles/input.styles.ts | 35 + constants/styles/layout.styles.ts | 52 + constants/styles/modal.styles.ts | 140 +++ constants/styles/spacing.styles.ts | 60 ++ constants/styles/typography.styles.ts | 28 + docs/FILE-HEALTH.md | 134 +++ lib/api.ts | 881 +---------------- lib/api/announcement.api.ts | 30 + lib/api/auth.api.ts | 46 + lib/api/banner.api.ts | 30 + lib/api/calendar.api.ts | 56 ++ lib/api/client.ts | 20 + lib/api/discussion.api.ts | 109 +++ lib/api/division.api.ts | 66 ++ lib/api/document.api.ts | 48 + lib/api/group.api.ts | 46 + lib/api/home.api.ts | 26 + lib/api/index.ts | 12 + lib/api/project.api.ts | 144 +++ lib/api/task.api.ts | 144 +++ lib/api/user.api.ts | 42 + 29 files changed, 1678 insertions(+), 2156 deletions(-) create mode 100644 constants/styles/border.styles.ts create mode 100644 constants/styles/button.styles.ts create mode 100644 constants/styles/card.styles.ts create mode 100644 constants/styles/component.styles.ts create mode 100644 constants/styles/header.styles.ts create mode 100644 constants/styles/index.ts create mode 100644 constants/styles/input.styles.ts create mode 100644 constants/styles/layout.styles.ts create mode 100644 constants/styles/modal.styles.ts create mode 100644 constants/styles/spacing.styles.ts create mode 100644 constants/styles/typography.styles.ts create mode 100644 docs/FILE-HEALTH.md create mode 100644 lib/api/announcement.api.ts create mode 100644 lib/api/auth.api.ts create mode 100644 lib/api/banner.api.ts create mode 100644 lib/api/calendar.api.ts create mode 100644 lib/api/client.ts create mode 100644 lib/api/discussion.api.ts create mode 100644 lib/api/division.api.ts create mode 100644 lib/api/document.api.ts create mode 100644 lib/api/group.api.ts create mode 100644 lib/api/home.api.ts create mode 100644 lib/api/index.ts create mode 100644 lib/api/project.api.ts create mode 100644 lib/api/task.api.ts create mode 100644 lib/api/user.api.ts diff --git a/CLAUDE.md b/CLAUDE.md index 21b35f3..8a00feb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -31,3 +31,7 @@ See @docs/ARCHITECTURE.md ## Key Conventions See @docs/CONVENTIONS.md + +## File Health + +See @docs/FILE-HEALTH.md diff --git a/constants/Styles.ts b/constants/Styles.ts index ada35aa..42d31a5 100644 --- a/constants/Styles.ts +++ b/constants/Styles.ts @@ -1,1276 +1 @@ -import { StyleSheet } from "react-native"; - -const Styles = StyleSheet.create({ - wrapLogin: { - flex: 1, - justifyContent: "flex-start", - alignItems: "stretch", - padding: 20, - }, - textHeaderHome: { - fontSize: 18, - fontWeight: 'bold', - flex: 1, - color: 'white' - }, - textDefault: { - fontSize: 15, - lineHeight: 24, - }, - textDefaultSemiBold: { - fontSize: 15, - lineHeight: 24, - fontWeight: '600', - }, - textMediumNormal: { - fontSize: 13, - lineHeight: 24, - }, - textMediumSemiBold: { - fontSize: 13, - lineHeight: 24, - fontWeight: '600', - }, - textSmallSemiBold: { - fontSize: 10, - fontWeight: '600', - }, - textTitle: { - fontSize: 32, - fontWeight: 'bold', - lineHeight: 32, - }, - textSubtitle: { - fontSize: 20, - fontWeight: 'bold', - }, - textSubtitle2: { - fontSize: 20, - }, - textLink: { - fontSize: 14, - color: '#0a7ea4', - }, - textInformation: { - fontSize: 12, - fontWeight: 'light', - }, - cError: { - color: '#DB1514' - }, - cGray: { - color: 'gray' - }, - cWhite: { - color: 'white' - }, - cBlack: { - color: 'black' - }, - cDefault: { - color: '#19345E' - }, - cFolder: { - color: '#f9cc40' - }, - mb05: { - marginBottom: 5 - }, - mb10: { - marginBottom: 10 - }, - mb12: { - marginBottom: 12 - }, - mb13: { - marginBottom: 13 - }, - mb15: { - marginBottom: 15 - }, - mb20: { - marginBottom: 20 - }, - mb30: { - marginBottom: 30 - }, - mb50: { - marginBottom: 50 - }, - mb100: { - marginBottom: 100 - }, - mv05: { - marginVertical: 5 - }, - mv15: { - marginVertical: 15 - }, - mh03: { - marginHorizontal: 3 - }, - mh05: { - marginHorizontal: 5 - }, - mh10: { - marginHorizontal: 10 - }, - mh15: { - marginHorizontal: 15 - }, - mv50: { - marginVertical: 50 - }, - mv10: { - marginVertical: 10 - }, - mt02: { - marginTop: 2 - }, - mt05: { - marginTop: 5 - }, - mt10: { - marginTop: 10 - }, - mt15: { - marginTop: 15 - }, - mt30: { - marginTop: 30 - }, - mr05: { - marginRight: 5 - }, - mr10: { - marginRight: 10 - }, - ml05: { - marginLeft: 5 - }, - ml10: { - marginLeft: 10 - }, - ml15: { - marginLeft: 15 - }, - ml20: { - marginLeft: 20 - }, - ml25: { - marginLeft: 25 - }, - p0: { - padding: 0 - }, - pb05: { - paddingBottom: 5 - }, - pb07: { - paddingBottom: 7 - }, - pb10: { - paddingBottom: 10 - }, - pb50: { - paddingBottom: 50 - }, - pb100: { - paddingBottom: 100 - }, - pb13: { - paddingBottom: 13 - }, - pb15: { - paddingBottom: 15 - }, - pb20: { - paddingBottom: 20 - }, - ph05: { - paddingHorizontal: 5, - }, - ph10: { - paddingHorizontal: 10, - }, - ph15: { - paddingHorizontal: 15, - }, - ph20: { - paddingHorizontal: 20, - }, - pv03: { - paddingVertical: 3 - }, - pv05: { - paddingVertical: 5 - }, - pv10: { - paddingVertical: 10 - }, - pv15: { - paddingVertical: 15 - }, - pv20: { - paddingVertical: 20 - }, - p05: { - padding: 5 - }, - p15: { - padding: 15 - }, - p10: { - padding: 10 - }, - p20: { - padding: 20 - }, - round05: { - borderRadius: 5 - }, - round08: { - borderRadius: 8 - }, - round10: { - borderRadius: 10 - }, - round15: { - borderRadius: 15 - }, - round20: { - borderRadius: 20 - }, - h100: { - height: '100%' - }, - w100: { - width: '100%' - }, - w48: { - width: '48%' - }, - w95: { - width: '95%' - }, - w90: { - width: '90%' - }, - w80: { - width: '80%' - }, - w70: { - width: '70%' - }, - w60: { - width: '60%' - }, - w50: { - width: '50%' - }, - w45: { - width: '45%' - }, - w40: { - width: '40%' - }, - w30: { - width: '30%' - }, - round30: { - borderRadius: 30 - }, - labelStatus: { - paddingHorizontal: 15, - borderRadius: 10 - }, - labelStatusSmall: { - paddingHorizontal: 10, - borderRadius: 10 - }, - rowSpaceBetween: { - justifyContent: 'space-between', - flexDirection: 'row' - }, - justifySpaceBetween: { - justifyContent: 'space-between' - }, - rowSpaceBetweenReverse: { - justifyContent: 'space-between', - flexDirection: 'row-reverse' - }, - rowItemsCenter: { - flexDirection: 'row', - alignItems: 'center' - }, - rowOnly: { - flexDirection: 'row' - }, - btnIconHeader: { - padding: 3, - }, - btnFiturMenu: { - padding: 13, - borderRadius: 15, - borderWidth: 1, - }, - btnRound: { - backgroundColor: '#1F3C88', - borderWidth: 0, - borderColor: '#1F3C88', - alignItems: 'center', - borderRadius: 30, - marginTop: 15, - paddingVertical: 10 - }, - btnTab: { - alignItems: 'center', - paddingVertical: 5, - paddingHorizontal: 15, - borderRadius: 20, - flexDirection: 'row', - justifyContent: 'center' - }, - btnLainnya: { - alignSelf: 'flex-start', - backgroundColor: '#1F3C88', - paddingVertical: 5, - marginVertical: 5 - }, - btnDisabled: { - backgroundColor: '#d6d8f6', - }, - btnMenuRow: { - width: '33%', - alignItems: 'center' - }, - btnMenuRowMany: { - alignItems: 'center', - marginHorizontal: 10 - }, - inputRoundForm: { - borderRadius: 5, - borderColor: '#d6d8f6', - borderWidth: 1, - paddingVertical: 10, - paddingHorizontal: 15, - }, - inputRoundFormLeft: { - flexDirection: 'row', - alignItems: 'center', - paddingVertical: 0, - }, - inputRoundFormRight: { - flexDirection: 'row-reverse', - alignItems: 'center', - paddingVertical: 0, - justifyContent: 'space-between' - }, - verificationCell: { - width: 50, - height: 50, - lineHeight: 45, - fontSize: 24, - borderWidth: 1, - borderRadius: 15, - borderColor: 'gray', - textAlign: 'center', - }, - verificationFocusCell: { - borderColor: '#19345E', - }, - caraoselContent: { - flex: 1, - justifyContent: "center", - marginHorizontal: 15, - borderRadius: 15, - backgroundColor: '#19345E', - display: 'flex', - width: '92%', - resizeMode: 'stretch', - overflow: 'hidden', - }, - wrapGridContent: { - shadowColor: '#171717', - shadowOffset: { width: 0, height: 0 }, - shadowOpacity: 0.1, - shadowRadius: 5, - elevation: 2, - borderRadius: 5, - marginBottom: 15 - }, - wrapGridCaraousel: { - width: '95%', - height: 200, - shadowColor: '#171717', - shadowOffset: { width: 0, height: 0 }, - shadowOpacity: 0.1, - shadowRadius: 5, - elevation: 2, - borderRadius: 5, - marginLeft: 5, - display: 'flex', - }, - headerPaperGrid: { - paddingVertical: 25, - paddingHorizontal: 20, - alignItems: 'center', - borderTopStartRadius: 5, - borderTopEndRadius: 5 - }, - contentPaperGrid: { - height: 125, - borderBottomEndRadius: 5, - borderBottomStartRadius: 5, - paddingHorizontal: 20, - justifyContent: 'space-evenly' - }, - contentPaperGrid2: { - height: 100, - borderBottomEndRadius: 5, - borderBottomStartRadius: 5, - paddingHorizontal: 20, - paddingVertical: 15, - justifyContent: 'flex-start' - }, - wrapBar: { - height: 20, - backgroundColor: '#ccc', - borderRadius: 10, - margin: 0, - width: '100%' - }, - contentBar: { - height: 20, - backgroundColor: '#3B82F6', - borderRadius: 10, - }, - wrapPaper: { - padding: 10, - backgroundColor: 'white', - borderRadius: 5, - // borderWidth: 1, - // borderColor: '#d6d8f6', - shadowColor: '#171717', - shadowOffset: { width: 0, height: 0 }, - shadowOpacity: 0.1, - shadowRadius: 5, - elevation: 2, - }, - noShadow: { - shadowColor: 'transparent', - shadowOffset: { width: 0, height: 0 }, - shadowOpacity: 0, - shadowRadius: 0, - elevation: 0, - }, - shadowBox: { - shadowColor: '#171717', - shadowOffset: { width: 0, height: 0 }, - shadowOpacity: 0.1, - shadowRadius: 5, - elevation: 2, - }, - contentItemCenter: { - justifyContent: 'center', - alignItems: 'center' - }, - itemEvent: { - padding: 10, - borderRadius: 10, - flexDirection: 'row', - alignContent: 'stretch', - marginBottom: 10 - }, - dividerEvent: { - width: 7, - borderRadius: 5, - marginRight: 10 - }, - wrapItemDiscussion: { - padding: 15, - borderRadius: 5, - // borderColor: '#d6d8f6', - borderBottomWidth: 1, - }, - wrapItemBorderBottom: { - padding: 10, - // borderColor: '#d6d8f6', - borderBottomWidth: 1, - }, - wrapItemBorderAll: { - padding: 10, - // borderColor: '#d6d8f6', - borderWidth: 1, - borderRadius: 5, - marginBottom: 5 - }, - wrapItemBorderNone: { - padding: 10, - marginBottom: 5 - }, - userProfileExtraSmall: { - width: 35, - height: 35, - borderRadius: 100 - }, - userProfileSmall: { - width: 48, - height: 48, - borderRadius: 100 - }, - userProfileBig: { - width: 100, - height: 100, - borderRadius: 100 - }, - imgListBanner: { - width: 100, - height: 50, - borderRadius: 5 - }, - iconContent: { - padding: 10, - borderRadius: 100, - backgroundColor: '#E5E7EB' - }, - wrapHeadViewMember: { - backgroundColor: '#19345E', - paddingVertical: 30, - paddingHorizontal: 15, - alignItems: 'center', - borderBottomLeftRadius: 25, - borderBottomRightRadius: 25 - }, - modalBgTransparant: { - backgroundColor: 'rgba(0, 0, 0, 0.3)', - flex: 1 - }, - modalContent: { - width: '100%', - paddingBottom: 20, - backgroundColor: 'white', - borderTopRightRadius: 18, - borderTopLeftRadius: 18, - position: 'absolute', - bottom: 0, - }, - titleContainer: { - backgroundColor: 'white', - borderTopRightRadius: 10, - borderTopLeftRadius: 10, - paddingHorizontal: 20, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - paddingVertical: 10 - }, - contentContainer: { - height: '90%' - }, - modalContentNew: { - width: '100%', - backgroundColor: 'white', - borderTopRightRadius: 18, - borderTopLeftRadius: 18, - paddingTop: 5, - paddingBottom: 5, - paddingHorizontal: 20 - }, - titleContainerNew: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - paddingVertical: 10, - }, - modalFloatContent: { - backgroundColor: 'white', - borderRadius: 18, - paddingTop: 5, - paddingBottom: 10, - paddingHorizontal: 20 - }, - titleContainerModalFloat: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - paddingVertical: 10, - }, - wrapBtnTab: { - justifyContent: 'space-between', - flexDirection: 'row', - marginBottom: 10, - borderRadius: 20, - padding: 5, - borderWidth: 1, - }, - itemSelectModal: { - padding: 10, - flexDirection: 'row', - justifyContent: 'space-between', - borderBottomWidth: 1, - alignItems: 'center' - }, - signDate: { - width: 20, - height: 2, - borderRadius: 3, - marginTop: 3 - }, - selectedDate: { - backgroundColor: '#238be6', - borderRadius: 5 - }, - selectRangeDate: { - backgroundColor: '#228be61f', - }, - bottomMenuSelectDocument: { - paddingVertical: 10, - position: 'absolute', - width: '100%', - bottom: 0, - }, - animatedView: { - width: '100%', - overflow: 'hidden', - }, - wrapperAccordion: { - width: '100%', - position: 'absolute', - display: 'flex', - alignItems: 'center', - }, - borderRight: { - borderRightWidth: 1, - borderRightColor: '#d6d8f6' - }, - borderLeft: { - borderLeftWidth: 1, - borderLeftColor: '#d6d8f6' - }, - borderBottom: { - borderBottomWidth: 1, - borderBottomColor: '#d6d8f6' - }, - borderTop: { - borderTopWidth: 1, - borderTopColor: '#d6d8f6' - }, - borderAll: { - borderWidth: 1, - borderColor: '#d6d8f6' - }, - absolute0: { - position: 'absolute', - bottom: 0 - }, - absoluteIcon: { - top: 18, - left: 20, - position: 'absolute' - }, - toastContainer: { - backgroundColor: 'white', - borderRadius: 10, - padding: 10, - width: '90%', - borderWidth: 1, - borderColor: '#d6d8f6', - }, - absoluteIconPicker: { - backgroundColor: '#384288', - padding: 5, - borderRadius: 100, - bottom: 5, - right: 5, - position: 'absolute' - }, - hidden: { - position: 'absolute', - opacity: 0, - zIndex: -1, - }, - headerContainer: { - backgroundColor: '#19345E', - }, - headerApp: { - // height: 40, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - paddingHorizontal: 16, - }, - headerTitle: { - color: '#fff', - fontSize: 18, - fontWeight: '600', - }, - headerSide: { - width: 40, - alignItems: 'center', - }, - chip: { - paddingVertical: 5, - paddingHorizontal: 15, - borderRadius: 5, - // backgroundColor: "#F3F4F6", - borderWidth: 1, - borderColor: "transparent", - marginRight: 10, - marginBottom: 10, - }, - chipSelected: { - backgroundColor: "#f2f6ffff", - borderColor: "#384288", - borderWidth: 1, - }, - chipText: { - fontSize: 16, - color: "#222", - }, - chipTextSelected: { - color: "white", - }, - checkIcon: { - position: "absolute", - top: -6, - left: -6, - backgroundColor: "#384288", - borderRadius: 10, - padding: 2, - }, - headerModalViewImg: { - paddingTop: 50, - paddingHorizontal: 16, - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - }, - wrapHomeCarousel: { - shadowColor: '#171717', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.15, - shadowRadius: 8, - elevation: 5, - }, - modalOverlay: { - flex: 1, - backgroundColor: 'rgba(0, 0, 0, 0.6)', - justifyContent: 'center', - alignItems: 'center', - }, - modalConfirmContainer: { - width: '80%', - borderRadius: 14, - overflow: 'hidden', - elevation: 2, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.25, - shadowRadius: 3.84, - }, - modalConfirmContent: { - padding: 20, - alignItems: 'center', - }, - modalConfirmTitle: { - fontSize: 18, - fontWeight: 'bold', - marginBottom: 8, - textAlign: 'center', - }, - modalConfirmMessage: { - fontSize: 14, - textAlign: 'center', - lineHeight: 20, - }, - modalConfirmDivider: { - height: 1, - width: '100%', - }, - modalConfirmFooter: { - flexDirection: 'row', - height: 50, - }, - modalConfirmButton: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, - modalConfirmButtonText: { - fontSize: 16, - }, - modalConfirmVerticalDivider: { - width: 1, - height: '100%', - }, - wrapGridItem: { - borderWidth: 1, - borderRadius: 5, - padding: 10, - flexDirection: 'row', - alignItems: 'center', - width: '48.5%', - marginBottom: 10, - }, - sectionCard: { - borderRadius: 12, - padding: 16, - borderWidth: 1, - }, - sectionHeader: { - flexDirection: 'row', - alignItems: 'center', - marginBottom: 12, - }, - sectionHeaderRow: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 10, - }, - sectionIconBox: { - width: 30, - height: 30, - borderRadius: 8, - alignItems: 'center', - justifyContent: 'center', - }, - badgeCol: { - alignItems: 'center', - gap: 6, - }, - progressBadge: { - borderRadius: 10, - paddingHorizontal: 12, - paddingVertical: 5, - borderWidth: 1, - alignItems: 'center', - }, - taskCountBadge: { - borderRadius: 6, - paddingHorizontal: 7, - paddingVertical: 2, - }, - textProgressPercent: { - fontSize: 22, - fontWeight: 'bold', - lineHeight: 28, - }, - progressTrack: { - height: 8, - borderRadius: 4, - overflow: 'hidden', - }, - progressFill: { - height: '100%', - borderRadius: 4, - }, - reportContent: { - borderLeftWidth: 3, - paddingLeft: 12, - }, - expandBtn: { - flexDirection: 'row', - alignItems: 'center', - alignSelf: 'flex-start', - marginTop: 8, - gap: 4, - }, - fileGrid: { - flexDirection: 'row', - flexWrap: 'wrap', - gap: 8, - }, - fileCard: { - width: '48%', - borderRadius: 10, - borderWidth: 1, - padding: 12, - flexDirection: 'row', - alignItems: 'center', - gap: 10, - }, - sectionActionRow: { - flexDirection: 'row', - alignItems: 'center', - gap: 10, - }, - sectionBadge: { - borderRadius: 10, - paddingHorizontal: 8, - paddingVertical: 2, - }, - positionBadge: { - borderRadius: 20, - paddingHorizontal: 8, - paddingVertical: 3, - }, - listItemCard: { - flexDirection: 'row', - alignItems: 'center', - backgroundColor: 'transparent', - borderRadius: 10, - borderWidth: 1, - paddingHorizontal: 12, - paddingVertical: 10, - gap: 12, - }, - flex1: { - flex: 1 - }, - flex2: { - flex: 2 - }, - flexColumn: { - flexDirection: 'column' - }, - textCenter: { - textAlign: 'center' - }, - posAbsolute: { - position: 'absolute' - }, - zIndex1: { - zIndex: 1 - }, - zIndexMinus1: { - zIndex: -1 - }, - alignCenter: { - alignItems: 'center' - }, - itemsCenter: { - alignItems: 'center' - }, - justifyCenter: { - justifyContent: 'center' - }, - resizeContain: { - resizeMode: 'contain' - }, - resizeCover: { - resizeMode: 'cover' - }, - resizeStretch: { - resizeMode: 'stretch' - }, - textWhite: { - color: 'white' - }, - font16: { - fontSize: 16 - }, - font26: { - fontSize: 26 - }, - ph16: { - paddingHorizontal: 16 - }, - alignStart: { - alignItems: 'flex-start' - }, - loadingCenter: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - justifyContent: 'center', - alignItems: 'center', - zIndex: 999, - backgroundColor: 'rgba(0,0,0,0.3)', - }, - loadingBox: { - paddingVertical: 15, - paddingHorizontal: 40, - borderRadius: 5, - alignItems: 'center', - gap: 10, - }, - modalUpdateContainer: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - paddingHorizontal: 30, - overflow: 'hidden', - }, - modalUpdateDecorativeCircle1: { - position: 'absolute', - width: 300, - height: 300, - borderRadius: 150, - backgroundColor: 'rgba(255, 255, 255, 0.05)', - top: -50, - right: -50, - }, - modalUpdateDecorativeCircle2: { - position: 'absolute', - width: 200, - height: 200, - borderRadius: 100, - backgroundColor: 'rgba(255, 255, 255, 0.03)', - bottom: -30, - left: -30, - }, - modalUpdateContent: { - width: '100%', - alignItems: 'flex-start', - zIndex: 1, - }, - modalUpdateLogo: { - width: 200, - height: 100, - marginBottom: 40, - alignSelf: 'center', - }, - modalUpdateTextContainer: { - marginBottom: 40, - }, - modalUpdateTitle: { - fontSize: 32, - fontWeight: 'bold', - color: 'white', - marginBottom: 20, - lineHeight: 38, - }, - modalUpdateDescription: { - fontSize: 16, - color: 'white', - lineHeight: 24, - }, - modalUpdateButtonContainer: { - width: '100%', - alignItems: 'center', - }, - modalUpdatePrimaryButton: { - width: '100%', - paddingVertical: 15, - borderRadius: 12, - alignItems: 'center', - justifyContent: 'center', - marginBottom: 15, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.2, - shadowRadius: 4, - elevation: 3, - }, - modalUpdatePrimaryButtonText: { - fontSize: 16, - fontWeight: 'bold', - }, - modalUpdateSecondaryButton: { - paddingVertical: 10, - }, - modalUpdateSecondaryButtonText: { - fontSize: 16, - color: 'white', - fontWeight: '500', - }, - pv14: { - paddingVertical: 14, - }, - mb08: { - marginBottom: 8, - }, - cWhiteDimmed: { - color: 'rgba(255,255,255,0.7)', - }, - memberAvatarRing: { - borderWidth: 3, - borderColor: 'rgba(255,255,255,0.4)', - borderRadius: 100, - }, - memberBadgeRow: { - flexDirection: 'row', - gap: 8, - marginTop: 12, - }, - memberBadgeApprover: { - paddingHorizontal: 10, - paddingVertical: 4, - borderRadius: 20, - borderWidth: 1, - borderColor: 'rgba(255,255,255,0.6)', - backgroundColor: 'rgba(255,255,255,0.15)', - }, - memberBadgePill: { - paddingHorizontal: 10, - paddingVertical: 4, - borderRadius: 20, - }, - memberInfoRow: { - flexDirection: 'row', - alignItems: 'center', - paddingVertical: 14, - }, - memberInfoIcon: { - width: 36, - alignItems: 'center', - }, - memberInfoContent: { - flex: 1, - marginLeft: 10, - }, - discussionCard: { - borderRadius: 10, - borderWidth: 1, - padding: 14, - }, - discussionIconCircle: { - width: 40, - height: 40, - borderRadius: 20, - alignItems: 'center', - justifyContent: 'center', - flexShrink: 0, - }, - discussionIconCircleLg: { - width: 44, - height: 44, - borderRadius: 22, - alignItems: 'center', - justifyContent: 'center', - }, - discussionStatusPill: { - alignSelf: 'flex-start', - marginTop: 3, - paddingHorizontal: 8, - paddingVertical: 2, - borderRadius: 20, - borderWidth: 1, - }, - discussionStatusText: { - fontSize: 11, - fontWeight: '600', - }, - discussionCardIndent: { - marginLeft: 50, - }, - discussionSeparator: { - height: 8, - }, - discussionCommentText: { - fontSize: 12, - marginLeft: 5, - }, - discussionDateText: { - fontSize: 11, - }, - discussionCommentCard: { - borderRadius: 10, - borderWidth: 1, - padding: 12, - marginBottom: 8, - flexDirection: 'row', - }, - discussionEditedText: { - fontSize: 10, - fontStyle: 'italic', - }, - - // guide overlay - guideOverlay: { - flex: 1, - backgroundColor: 'rgba(0,0,0,0.6)', - justifyContent: 'center', - alignItems: 'center', - }, - guideCard: { - position: 'absolute', - left: 24, - right: 24, - borderRadius: 16, - padding: 20, - shadowColor: '#000', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.2, - shadowRadius: 12, - elevation: 8, - }, - guideBadge: { - paddingHorizontal: 8, - paddingVertical: 3, - borderRadius: 20, - }, - guideDotRow: { - marginTop: 16, - gap: 6, - justifyContent: 'center', - }, - guideDot: { - width: 6, - height: 6, - borderRadius: 3, - }, - guideButtonPrimary: { - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: 16, - paddingVertical: 8, - borderRadius: 20, - }, - guideButtonSecondary: { - paddingHorizontal: 4, - paddingVertical: 8, - }, - guideArrowUp: { - position: 'absolute', - top: -10, - marginLeft: -8, - width: 0, - height: 0, - borderLeftWidth: 8, - borderRightWidth: 8, - borderBottomWidth: 10, - borderLeftColor: 'transparent', - borderRightColor: 'transparent', - }, - guideArrowDown: { - position: 'absolute', - bottom: -10, - marginLeft: -8, - width: 0, - height: 0, - borderLeftWidth: 8, - borderRightWidth: 8, - borderTopWidth: 10, - borderLeftColor: 'transparent', - borderRightColor: 'transparent', - }, - - // village calendar & itemDateCalendar - calendarDotRow: { - flexDirection: 'row', - gap: 2, - height: 6, - marginTop: 1, - }, - calendarDot: { - width: 5, - height: 5, - borderRadius: 3, - }, - villageEventLegendRow: { - marginTop: 10, - marginBottom: 4, - gap: 16, - }, - villageEventLegendItem: { - gap: 6, - }, - villageEventLegendDot: { - width: 10, - height: 10, - borderRadius: 5, - }, - villageEventBadge: { - paddingHorizontal: 6, - paddingVertical: 2, - borderRadius: 4, - marginRight: 6, - }, -}) - -export default Styles; \ No newline at end of file +export { default } from './styles/index'; diff --git a/constants/styles/border.styles.ts b/constants/styles/border.styles.ts new file mode 100644 index 0000000..834ae46 --- /dev/null +++ b/constants/styles/border.styles.ts @@ -0,0 +1,17 @@ +import { StyleSheet } from "react-native"; + +const BorderStyles = StyleSheet.create({ + round05: { borderRadius: 5 }, + round08: { borderRadius: 8 }, + round10: { borderRadius: 10 }, + round15: { borderRadius: 15 }, + round20: { borderRadius: 20 }, + round30: { borderRadius: 30 }, + borderRight: { borderRightWidth: 1, borderRightColor: '#d6d8f6' }, + borderLeft: { borderLeftWidth: 1, borderLeftColor: '#d6d8f6' }, + borderBottom: { borderBottomWidth: 1, borderBottomColor: '#d6d8f6' }, + borderTop: { borderTopWidth: 1, borderTopColor: '#d6d8f6' }, + borderAll: { borderWidth: 1, borderColor: '#d6d8f6' }, +}); + +export default BorderStyles; diff --git a/constants/styles/button.styles.ts b/constants/styles/button.styles.ts new file mode 100644 index 0000000..b21a560 --- /dev/null +++ b/constants/styles/button.styles.ts @@ -0,0 +1,44 @@ +import { StyleSheet } from "react-native"; + +const ButtonStyles = StyleSheet.create({ + btnIconHeader: { padding: 3 }, + btnFiturMenu: { padding: 13, borderRadius: 15, borderWidth: 1 }, + btnRound: { + backgroundColor: '#1F3C88', + borderWidth: 0, + borderColor: '#1F3C88', + alignItems: 'center', + borderRadius: 30, + marginTop: 15, + paddingVertical: 10, + }, + btnTab: { + alignItems: 'center', + paddingVertical: 5, + paddingHorizontal: 15, + borderRadius: 20, + flexDirection: 'row', + justifyContent: 'center', + }, + btnLainnya: { + alignSelf: 'flex-start', + backgroundColor: '#1F3C88', + paddingVertical: 5, + marginVertical: 5, + }, + btnDisabled: { backgroundColor: '#d6d8f6' }, + btnMenuRow: { width: '33%', alignItems: 'center' }, + btnMenuRowMany: { alignItems: 'center', marginHorizontal: 10 }, + wrapBtnTab: { + justifyContent: 'space-between', + flexDirection: 'row', + marginBottom: 10, + borderRadius: 20, + padding: 5, + borderWidth: 1, + }, + labelStatus: { paddingHorizontal: 15, borderRadius: 10 }, + labelStatusSmall: { paddingHorizontal: 10, borderRadius: 10 }, +}); + +export default ButtonStyles; diff --git a/constants/styles/card.styles.ts b/constants/styles/card.styles.ts new file mode 100644 index 0000000..e57d327 --- /dev/null +++ b/constants/styles/card.styles.ts @@ -0,0 +1,159 @@ +import { StyleSheet } from "react-native"; + +const CardStyles = StyleSheet.create({ + wrapPaper: { + padding: 10, + backgroundColor: 'white', + borderRadius: 5, + shadowColor: '#171717', + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.1, + shadowRadius: 5, + elevation: 2, + }, + shadowBox: { + shadowColor: '#171717', + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.1, + shadowRadius: 5, + elevation: 2, + }, + noShadow: { + shadowColor: 'transparent', + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0, + shadowRadius: 0, + elevation: 0, + }, + wrapGridContent: { + shadowColor: '#171717', + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.1, + shadowRadius: 5, + elevation: 2, + borderRadius: 5, + marginBottom: 15, + }, + wrapGridCaraousel: { + width: '95%', + height: 200, + shadowColor: '#171717', + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.1, + shadowRadius: 5, + elevation: 2, + borderRadius: 5, + marginLeft: 5, + display: 'flex', + }, + wrapHomeCarousel: { + shadowColor: '#171717', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.15, + shadowRadius: 8, + elevation: 5, + }, + headerPaperGrid: { + paddingVertical: 25, + paddingHorizontal: 20, + alignItems: 'center', + borderTopStartRadius: 5, + borderTopEndRadius: 5, + }, + contentPaperGrid: { + height: 125, + borderBottomEndRadius: 5, + borderBottomStartRadius: 5, + paddingHorizontal: 20, + justifyContent: 'space-evenly', + }, + contentPaperGrid2: { + height: 100, + borderBottomEndRadius: 5, + borderBottomStartRadius: 5, + paddingHorizontal: 20, + paddingVertical: 15, + justifyContent: 'flex-start', + }, + wrapGridItem: { + borderWidth: 1, + borderRadius: 5, + padding: 10, + flexDirection: 'row', + alignItems: 'center', + width: '48.5%', + marginBottom: 10, + }, + listItemCard: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: 'transparent', + borderRadius: 10, + borderWidth: 1, + paddingHorizontal: 12, + paddingVertical: 10, + gap: 12, + }, + sectionCard: { borderRadius: 12, padding: 16, borderWidth: 1 }, + sectionHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 12 }, + sectionHeaderRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 10, + }, + sectionIconBox: { + width: 30, + height: 30, + borderRadius: 8, + alignItems: 'center', + justifyContent: 'center', + }, + sectionActionRow: { flexDirection: 'row', alignItems: 'center', gap: 10 }, + sectionBadge: { borderRadius: 10, paddingHorizontal: 8, paddingVertical: 2 }, + wrapBar: { height: 20, backgroundColor: '#ccc', borderRadius: 10, margin: 0, width: '100%' }, + contentBar: { height: 20, backgroundColor: '#3B82F6', borderRadius: 10 }, + toastContainer: { + backgroundColor: 'white', + borderRadius: 10, + padding: 10, + width: '90%', + borderWidth: 1, + borderColor: '#d6d8f6', + }, + loadingCenter: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'center', + alignItems: 'center', + zIndex: 999, + backgroundColor: 'rgba(0,0,0,0.3)', + }, + loadingBox: { + paddingVertical: 15, + paddingHorizontal: 40, + borderRadius: 5, + alignItems: 'center', + gap: 10, + }, + caraoselContent: { + flex: 1, + justifyContent: "center", + marginHorizontal: 15, + borderRadius: 15, + backgroundColor: '#19345E', + display: 'flex', + width: '92%', + resizeMode: 'stretch', + overflow: 'hidden', + }, + wrapItemDiscussion: { padding: 15, borderRadius: 5, borderBottomWidth: 1 }, + wrapItemBorderBottom: { padding: 10, borderBottomWidth: 1 }, + wrapItemBorderAll: { padding: 10, borderWidth: 1, borderRadius: 5, marginBottom: 5 }, + wrapItemBorderNone: { padding: 10, marginBottom: 5 }, +}); + +export default CardStyles; diff --git a/constants/styles/component.styles.ts b/constants/styles/component.styles.ts new file mode 100644 index 0000000..1fc0369 --- /dev/null +++ b/constants/styles/component.styles.ts @@ -0,0 +1,135 @@ +import { StyleSheet } from "react-native"; + +const ComponentStyles = StyleSheet.create({ + // avatar + userProfileExtraSmall: { width: 35, height: 35, borderRadius: 100 }, + userProfileSmall: { width: 48, height: 48, borderRadius: 100 }, + userProfileBig: { width: 100, height: 100, borderRadius: 100 }, + imgListBanner: { width: 100, height: 50, borderRadius: 5 }, + iconContent: { padding: 10, borderRadius: 100, backgroundColor: '#E5E7EB' }, + + // chip + chip: { + paddingVertical: 5, + paddingHorizontal: 15, + borderRadius: 5, + borderWidth: 1, + borderColor: "transparent", + marginRight: 10, + marginBottom: 10, + }, + chipSelected: { backgroundColor: "#f2f6ffff", borderColor: "#384288", borderWidth: 1 }, + chipText: { fontSize: 16, color: "#222" }, + chipTextSelected: { color: "white" }, + checkIcon: { + position: "absolute", + top: -6, + left: -6, + backgroundColor: "#384288", + borderRadius: 10, + padding: 2, + }, + + // badge & progress + badgeCol: { alignItems: 'center', gap: 6 }, + progressBadge: { borderRadius: 10, paddingHorizontal: 12, paddingVertical: 5, borderWidth: 1, alignItems: 'center' }, + taskCountBadge: { borderRadius: 6, paddingHorizontal: 7, paddingVertical: 2 }, + positionBadge: { borderRadius: 20, paddingHorizontal: 8, paddingVertical: 3 }, + textProgressPercent: { fontSize: 22, fontWeight: 'bold', lineHeight: 28 }, + progressTrack: { height: 8, borderRadius: 4, overflow: 'hidden' }, + progressFill: { height: '100%', borderRadius: 4 }, + reportContent: { borderLeftWidth: 3, paddingLeft: 12 }, + expandBtn: { flexDirection: 'row', alignItems: 'center', alignSelf: 'flex-start', marginTop: 8, gap: 4 }, + fileGrid: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 }, + fileCard: { width: '48%', borderRadius: 10, borderWidth: 1, padding: 12, flexDirection: 'row', alignItems: 'center', gap: 10 }, + + // calendar + signDate: { width: 20, height: 2, borderRadius: 3, marginTop: 3 }, + selectedDate: { backgroundColor: '#238be6', borderRadius: 5 }, + selectRangeDate: { backgroundColor: '#228be61f' }, + calendarDotRow: { flexDirection: 'row', gap: 2, height: 6, marginTop: 1 }, + calendarDot: { width: 5, height: 5, borderRadius: 3 }, + villageEventLegendRow: { marginTop: 10, marginBottom: 4, gap: 16 }, + villageEventLegendItem: { gap: 6 }, + villageEventLegendDot: { width: 10, height: 10, borderRadius: 5 }, + villageEventBadge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 4, marginRight: 6 }, + + // event item + itemEvent: { padding: 10, borderRadius: 10, flexDirection: 'row', alignContent: 'stretch', marginBottom: 10 }, + dividerEvent: { width: 7, borderRadius: 5, marginRight: 10 }, + + // member + memberAvatarRing: { borderWidth: 3, borderColor: 'rgba(255,255,255,0.4)', borderRadius: 100 }, + memberBadgeRow: { flexDirection: 'row', gap: 8, marginTop: 12 }, + memberBadgeApprover: { + paddingHorizontal: 10, + paddingVertical: 4, + borderRadius: 20, + borderWidth: 1, + borderColor: 'rgba(255,255,255,0.6)', + backgroundColor: 'rgba(255,255,255,0.15)', + }, + memberBadgePill: { paddingHorizontal: 10, paddingVertical: 4, borderRadius: 20 }, + memberInfoRow: { flexDirection: 'row', alignItems: 'center', paddingVertical: 14 }, + memberInfoIcon: { width: 36, alignItems: 'center' }, + memberInfoContent: { flex: 1, marginLeft: 10 }, + + // discussion + discussionCard: { borderRadius: 10, borderWidth: 1, padding: 14 }, + discussionIconCircle: { width: 40, height: 40, borderRadius: 20, alignItems: 'center', justifyContent: 'center', flexShrink: 0 }, + discussionIconCircleLg: { width: 44, height: 44, borderRadius: 22, alignItems: 'center', justifyContent: 'center' }, + discussionStatusPill: { alignSelf: 'flex-start', marginTop: 3, paddingHorizontal: 8, paddingVertical: 2, borderRadius: 20, borderWidth: 1 }, + discussionStatusText: { fontSize: 11, fontWeight: '600' }, + discussionCardIndent: { marginLeft: 50 }, + discussionSeparator: { height: 8 }, + discussionCommentText: { fontSize: 12, marginLeft: 5 }, + discussionDateText: { fontSize: 11 }, + discussionCommentCard: { borderRadius: 10, borderWidth: 1, padding: 12, marginBottom: 8, flexDirection: 'row' }, + discussionEditedText: { fontSize: 10, fontStyle: 'italic' }, + + // guide overlay + guideOverlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.6)', justifyContent: 'center', alignItems: 'center' }, + guideCard: { + position: 'absolute', + left: 24, + right: 24, + borderRadius: 16, + padding: 20, + shadowColor: '#000', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.2, + shadowRadius: 12, + elevation: 8, + }, + guideBadge: { paddingHorizontal: 8, paddingVertical: 3, borderRadius: 20 }, + guideDotRow: { marginTop: 16, gap: 6, justifyContent: 'center' }, + guideDot: { width: 6, height: 6, borderRadius: 3 }, + guideButtonPrimary: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20 }, + guideButtonSecondary: { paddingHorizontal: 4, paddingVertical: 8 }, + guideArrowUp: { + position: 'absolute', + top: -10, + marginLeft: -8, + width: 0, + height: 0, + borderLeftWidth: 8, + borderRightWidth: 8, + borderBottomWidth: 10, + borderLeftColor: 'transparent', + borderRightColor: 'transparent', + }, + guideArrowDown: { + position: 'absolute', + bottom: -10, + marginLeft: -8, + width: 0, + height: 0, + borderLeftWidth: 8, + borderRightWidth: 8, + borderTopWidth: 10, + borderLeftColor: 'transparent', + borderRightColor: 'transparent', + }, +}); + +export default ComponentStyles; diff --git a/constants/styles/header.styles.ts b/constants/styles/header.styles.ts new file mode 100644 index 0000000..dc5f7b2 --- /dev/null +++ b/constants/styles/header.styles.ts @@ -0,0 +1,23 @@ +import { StyleSheet } from "react-native"; + +const HeaderStyles = StyleSheet.create({ + headerContainer: { backgroundColor: '#19345E' }, + headerApp: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingHorizontal: 16, + }, + headerTitle: { color: '#fff', fontSize: 18, fontWeight: '600' }, + headerSide: { width: 40, alignItems: 'center' }, + wrapHeadViewMember: { + backgroundColor: '#19345E', + paddingVertical: 30, + paddingHorizontal: 15, + alignItems: 'center', + borderBottomLeftRadius: 25, + borderBottomRightRadius: 25, + }, +}); + +export default HeaderStyles; diff --git a/constants/styles/index.ts b/constants/styles/index.ts new file mode 100644 index 0000000..dbae1b1 --- /dev/null +++ b/constants/styles/index.ts @@ -0,0 +1,26 @@ +import { StyleSheet } from "react-native"; +import SpacingStyles from './spacing.styles'; +import TypographyStyles from './typography.styles'; +import LayoutStyles from './layout.styles'; +import BorderStyles from './border.styles'; +import ButtonStyles from './button.styles'; +import InputStyles from './input.styles'; +import CardStyles from './card.styles'; +import ModalStyles from './modal.styles'; +import HeaderStyles from './header.styles'; +import ComponentStyles from './component.styles'; + +const Styles = StyleSheet.create({ + ...SpacingStyles, + ...TypographyStyles, + ...LayoutStyles, + ...BorderStyles, + ...ButtonStyles, + ...InputStyles, + ...CardStyles, + ...ModalStyles, + ...HeaderStyles, + ...ComponentStyles, +}); + +export default Styles; diff --git a/constants/styles/input.styles.ts b/constants/styles/input.styles.ts new file mode 100644 index 0000000..7515eee --- /dev/null +++ b/constants/styles/input.styles.ts @@ -0,0 +1,35 @@ +import { StyleSheet } from "react-native"; + +const InputStyles = StyleSheet.create({ + inputRoundForm: { + borderRadius: 5, + borderColor: '#d6d8f6', + borderWidth: 1, + paddingVertical: 10, + paddingHorizontal: 15, + }, + inputRoundFormLeft: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: 0, + }, + inputRoundFormRight: { + flexDirection: 'row-reverse', + alignItems: 'center', + paddingVertical: 0, + justifyContent: 'space-between', + }, + verificationCell: { + width: 50, + height: 50, + lineHeight: 45, + fontSize: 24, + borderWidth: 1, + borderRadius: 15, + borderColor: 'gray', + textAlign: 'center', + }, + verificationFocusCell: { borderColor: '#19345E' }, +}); + +export default InputStyles; diff --git a/constants/styles/layout.styles.ts b/constants/styles/layout.styles.ts new file mode 100644 index 0000000..b93f544 --- /dev/null +++ b/constants/styles/layout.styles.ts @@ -0,0 +1,52 @@ +import { StyleSheet } from "react-native"; + +const LayoutStyles = StyleSheet.create({ + wrapLogin: { flex: 1, justifyContent: "flex-start", alignItems: "stretch", padding: 20 }, + flex1: { flex: 1 }, + flex2: { flex: 2 }, + flexColumn: { flexDirection: 'column' }, + rowOnly: { flexDirection: 'row' }, + rowSpaceBetween: { justifyContent: 'space-between', flexDirection: 'row' }, + rowSpaceBetweenReverse: { justifyContent: 'space-between', flexDirection: 'row-reverse' }, + rowItemsCenter: { flexDirection: 'row', alignItems: 'center' }, + justifySpaceBetween: { justifyContent: 'space-between' }, + justifyCenter: { justifyContent: 'center' }, + alignCenter: { alignItems: 'center' }, + itemsCenter: { alignItems: 'center' }, + alignStart: { alignItems: 'flex-start' }, + contentItemCenter: { justifyContent: 'center', alignItems: 'center' }, + h100: { height: '100%' }, + w30: { width: '30%' }, + w40: { width: '40%' }, + w45: { width: '45%' }, + w48: { width: '48%' }, + w50: { width: '50%' }, + w60: { width: '60%' }, + w70: { width: '70%' }, + w80: { width: '80%' }, + w90: { width: '90%' }, + w95: { width: '95%' }, + w100: { width: '100%' }, + posAbsolute: { position: 'absolute' }, + absolute0: { position: 'absolute', bottom: 0 }, + absoluteIcon: { top: 18, left: 20, position: 'absolute' }, + absoluteIconPicker: { + backgroundColor: '#384288', + padding: 5, + borderRadius: 100, + bottom: 5, + right: 5, + position: 'absolute', + }, + hidden: { position: 'absolute', opacity: 0, zIndex: -1 }, + zIndex1: { zIndex: 1 }, + zIndexMinus1: { zIndex: -1 }, + resizeContain: { resizeMode: 'contain' }, + resizeCover: { resizeMode: 'cover' }, + resizeStretch: { resizeMode: 'stretch' }, + animatedView: { width: '100%', overflow: 'hidden' }, + wrapperAccordion: { width: '100%', position: 'absolute', display: 'flex', alignItems: 'center' }, + bottomMenuSelectDocument: { paddingVertical: 10, position: 'absolute', width: '100%', bottom: 0 }, +}); + +export default LayoutStyles; diff --git a/constants/styles/modal.styles.ts b/constants/styles/modal.styles.ts new file mode 100644 index 0000000..4948171 --- /dev/null +++ b/constants/styles/modal.styles.ts @@ -0,0 +1,140 @@ +import { StyleSheet } from "react-native"; + +const ModalStyles = StyleSheet.create({ + modalBgTransparant: { backgroundColor: 'rgba(0, 0, 0, 0.3)', flex: 1 }, + modalContent: { + width: '100%', + paddingBottom: 20, + backgroundColor: 'white', + borderTopRightRadius: 18, + borderTopLeftRadius: 18, + position: 'absolute', + bottom: 0, + }, + modalContentNew: { + width: '100%', + backgroundColor: 'white', + borderTopRightRadius: 18, + borderTopLeftRadius: 18, + paddingTop: 5, + paddingBottom: 5, + paddingHorizontal: 20, + }, + modalFloatContent: { + backgroundColor: 'white', + borderRadius: 18, + paddingTop: 5, + paddingBottom: 10, + paddingHorizontal: 20, + }, + titleContainer: { + backgroundColor: 'white', + borderTopRightRadius: 10, + borderTopLeftRadius: 10, + paddingHorizontal: 20, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingVertical: 10, + }, + titleContainerNew: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingVertical: 10, + }, + titleContainerModalFloat: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + paddingVertical: 10, + }, + contentContainer: { height: '90%' }, + itemSelectModal: { + padding: 10, + flexDirection: 'row', + justifyContent: 'space-between', + borderBottomWidth: 1, + alignItems: 'center', + }, + modalOverlay: { + flex: 1, + backgroundColor: 'rgba(0, 0, 0, 0.6)', + justifyContent: 'center', + alignItems: 'center', + }, + modalConfirmContainer: { + width: '80%', + borderRadius: 14, + overflow: 'hidden', + elevation: 2, + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.25, + shadowRadius: 3.84, + }, + modalConfirmContent: { padding: 20, alignItems: 'center' }, + modalConfirmTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 8, textAlign: 'center' }, + modalConfirmMessage: { fontSize: 14, textAlign: 'center', lineHeight: 20 }, + modalConfirmDivider: { height: 1, width: '100%' }, + modalConfirmFooter: { flexDirection: 'row', height: 50 }, + modalConfirmButton: { flex: 1, justifyContent: 'center', alignItems: 'center' }, + modalConfirmButtonText: { fontSize: 16 }, + modalConfirmVerticalDivider: { width: 1, height: '100%' }, + modalUpdateContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + paddingHorizontal: 30, + overflow: 'hidden', + }, + modalUpdateDecorativeCircle1: { + position: 'absolute', + width: 300, + height: 300, + borderRadius: 150, + backgroundColor: 'rgba(255, 255, 255, 0.05)', + top: -50, + right: -50, + }, + modalUpdateDecorativeCircle2: { + position: 'absolute', + width: 200, + height: 200, + borderRadius: 100, + backgroundColor: 'rgba(255, 255, 255, 0.03)', + bottom: -30, + left: -30, + }, + modalUpdateContent: { width: '100%', alignItems: 'flex-start', zIndex: 1 }, + modalUpdateLogo: { width: 200, height: 100, marginBottom: 40, alignSelf: 'center' }, + modalUpdateTextContainer: { marginBottom: 40 }, + modalUpdateTitle: { fontSize: 32, fontWeight: 'bold', color: 'white', marginBottom: 20, lineHeight: 38 }, + modalUpdateDescription: { fontSize: 16, color: 'white', lineHeight: 24 }, + modalUpdateButtonContainer: { width: '100%', alignItems: 'center' }, + modalUpdatePrimaryButton: { + width: '100%', + paddingVertical: 15, + borderRadius: 12, + alignItems: 'center', + justifyContent: 'center', + marginBottom: 15, + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.2, + shadowRadius: 4, + elevation: 3, + }, + modalUpdatePrimaryButtonText: { fontSize: 16, fontWeight: 'bold' }, + modalUpdateSecondaryButton: { paddingVertical: 10 }, + modalUpdateSecondaryButtonText: { fontSize: 16, color: 'white', fontWeight: '500' }, + headerModalViewImg: { + paddingTop: 50, + paddingHorizontal: 16, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, +}); + +export default ModalStyles; diff --git a/constants/styles/spacing.styles.ts b/constants/styles/spacing.styles.ts new file mode 100644 index 0000000..1d822a5 --- /dev/null +++ b/constants/styles/spacing.styles.ts @@ -0,0 +1,60 @@ +import { StyleSheet } from "react-native"; + +const SpacingStyles = StyleSheet.create({ + mb05: { marginBottom: 5 }, + mb08: { marginBottom: 8 }, + mb10: { marginBottom: 10 }, + mb12: { marginBottom: 12 }, + mb13: { marginBottom: 13 }, + mb15: { marginBottom: 15 }, + mb20: { marginBottom: 20 }, + mb30: { marginBottom: 30 }, + mb50: { marginBottom: 50 }, + mb100: { marginBottom: 100 }, + mt02: { marginTop: 2 }, + mt05: { marginTop: 5 }, + mt10: { marginTop: 10 }, + mt15: { marginTop: 15 }, + mt30: { marginTop: 30 }, + mr05: { marginRight: 5 }, + mr10: { marginRight: 10 }, + ml05: { marginLeft: 5 }, + ml10: { marginLeft: 10 }, + ml15: { marginLeft: 15 }, + ml20: { marginLeft: 20 }, + ml25: { marginLeft: 25 }, + mv05: { marginVertical: 5 }, + mv10: { marginVertical: 10 }, + mv15: { marginVertical: 15 }, + mv50: { marginVertical: 50 }, + mh03: { marginHorizontal: 3 }, + mh05: { marginHorizontal: 5 }, + mh10: { marginHorizontal: 10 }, + mh15: { marginHorizontal: 15 }, + p0: { padding: 0 }, + p05: { padding: 5 }, + p10: { padding: 10 }, + p15: { padding: 15 }, + p20: { padding: 20 }, + pb05: { paddingBottom: 5 }, + pb07: { paddingBottom: 7 }, + pb10: { paddingBottom: 10 }, + pb13: { paddingBottom: 13 }, + pb15: { paddingBottom: 15 }, + pb20: { paddingBottom: 20 }, + pb50: { paddingBottom: 50 }, + pb100: { paddingBottom: 100 }, + ph05: { paddingHorizontal: 5 }, + ph10: { paddingHorizontal: 10 }, + ph15: { paddingHorizontal: 15 }, + ph16: { paddingHorizontal: 16 }, + ph20: { paddingHorizontal: 20 }, + pv03: { paddingVertical: 3 }, + pv05: { paddingVertical: 5 }, + pv10: { paddingVertical: 10 }, + pv14: { paddingVertical: 14 }, + pv15: { paddingVertical: 15 }, + pv20: { paddingVertical: 20 }, +}); + +export default SpacingStyles; diff --git a/constants/styles/typography.styles.ts b/constants/styles/typography.styles.ts new file mode 100644 index 0000000..9a689ea --- /dev/null +++ b/constants/styles/typography.styles.ts @@ -0,0 +1,28 @@ +import { StyleSheet } from "react-native"; + +const TypographyStyles = StyleSheet.create({ + textTitle: { fontSize: 32, fontWeight: 'bold', lineHeight: 32 }, + textSubtitle: { fontSize: 20, fontWeight: 'bold' }, + textSubtitle2: { fontSize: 20 }, + textHeaderHome: { fontSize: 18, fontWeight: 'bold', flex: 1, color: 'white' }, + textDefault: { fontSize: 15, lineHeight: 24 }, + textDefaultSemiBold: { fontSize: 15, lineHeight: 24, fontWeight: '600' }, + textMediumNormal: { fontSize: 13, lineHeight: 24 }, + textMediumSemiBold: { fontSize: 13, lineHeight: 24, fontWeight: '600' }, + textSmallSemiBold: { fontSize: 10, fontWeight: '600' }, + textInformation: { fontSize: 12, fontWeight: 'light' }, + textLink: { fontSize: 14, color: '#0a7ea4' }, + textCenter: { textAlign: 'center' }, + textWhite: { color: 'white' }, + font16: { fontSize: 16 }, + font26: { fontSize: 26 }, + cError: { color: '#DB1514' }, + cGray: { color: 'gray' }, + cWhite: { color: 'white' }, + cWhiteDimmed: { color: 'rgba(255,255,255,0.7)' }, + cBlack: { color: 'black' }, + cDefault: { color: '#19345E' }, + cFolder: { color: '#f9cc40' }, +}); + +export default TypographyStyles; diff --git a/docs/FILE-HEALTH.md b/docs/FILE-HEALTH.md new file mode 100644 index 0000000..5074fdb --- /dev/null +++ b/docs/FILE-HEALTH.md @@ -0,0 +1,134 @@ +# FILE-HEALTH — Aturan Ukuran & Struktur File + +Aturan ini berlaku untuk semua file dalam project ini. +Tujuan: menjaga file tetap kecil, kohesif, dan mudah diproses oleh AI maupun manusia. + +--- + +## Batas Ukuran File + +| Tipe File | Maks Baris | Maks Karakter | Keterangan | +|-----------|-----------|---------------|------------| +| Route handler | 150 | 6.000 | Satu file = satu resource | +| Service / use-case | 300 | 12.000 | Satu file = satu domain logic | +| Repository / query | 250 | 10.000 | Pisah per entity | +| Schema / validation | 200 | 8.000 | Pisah per domain | +| Types / interfaces | 300 | 10.000 | Boleh agregat, tapi per modul | +| Utility / helper | 200 | 8.000 | Satu concern per file | +| Config | 100 | 4.000 | Tidak ada logic bisnis | +| Test file | 400 | 16.000 | Satu file test per satu unit | + +> **Hard limit global:** Tidak ada file yang boleh melebihi **500 baris** atau **20.000 karakter**, +> kecuali file yang di-generate otomatis (migration, seed, generated types). + +--- + +## Aturan Wajib + +### 1. Satu File, Satu Tanggung Jawab +- Setiap file harus bisa dijelaskan dalam satu kalimat pendek. +- Jika penjelasannya butuh kata "dan" lebih dari sekali → **pecah file-nya**. + +### 2. Tidak Ada "God File" +- Dilarang menaruh lebih dari satu route group dalam satu file handler. +- Dilarang mencampur business logic dengan transport layer (HTTP, WS, queue). +- Dilarang mencampur type definition dengan implementation dalam satu file yang panjang. + +### 3. Penamaan File Harus Eksplisit +- Nama file harus mencerminkan isi secara tepat. +- Hindari nama generik: `utils.ts`, `helpers.ts`, `common.ts`, `misc.ts`. +- Gunakan pola: `[domain].[layer].ts` → contoh: `user.service.ts`, `payment.repository.ts`. + +### 4. Index File Hanya Untuk Re-export +- File `index.ts` hanya boleh berisi re-export, **bukan** implementasi. +- Maksimal 50 baris untuk file index. + +### 5. Tidak Ada Barrel Import yang Dalam +- Hindari barrel yang mengimpor dari barrel lain lebih dari 2 level. +- Ini membuat AI sulit trace dependency dengan akurat. + +--- + +## Kapan Harus Pecah File + +Pecah file segera jika salah satu kondisi ini terpenuhi: + +- [ ] File melebihi batas karakter/baris di tabel di atas +- [ ] Ada dua fungsi/class yang tidak saling bergantung dalam satu file +- [ ] File mengandung lebih dari 3 exported symbol utama +- [ ] File sulit diberi nama yang spesifik tanpa kata "dan" +- [ ] Edit di satu bagian file sering menyebabkan konflik di bagian lain + +--- + +## Pola Pemecahan File yang Dianjurkan + +### Service yang Terlalu Besar +``` +// SEBELUM: user.service.ts (600 baris) + +// SESUDAH: +user.service.ts // orchestration, max 150 baris +user.query.service.ts // read operations +user.command.service.ts // write operations +user.notification.service.ts // side effects +``` + +### Handler yang Terlalu Besar +``` +// SEBELUM: user.route.ts (400 baris) + +// SESUDAH: +user.route.ts // route registration only +user.handler.ts // handler functions +user.middleware.ts // route-specific middleware +``` + +### Types yang Terlalu Besar +``` +// SEBELUM: types.ts (500 baris) + +// SESUDAH: +types/user.types.ts +types/payment.types.ts +types/shared.types.ts +``` + +--- + +## Instruksi Khusus untuk AI + +Ketika bekerja dalam project ini, **Claude wajib**: + +1. **Menolak menambah kode** ke file yang sudah mendekati atau melebihi batas, + kecuali penambahannya memang sangat kecil (< 10 baris) dan kohesif. + +2. **Proaktif menyarankan refactor** saat mendeteksi file yang tumbuh tidak sehat, + sebelum menambahkan fitur baru ke file tersebut. + +3. **Tidak membuat "helper dump"** — setiap helper harus punya file sendiri + yang namanya spesifik, bukan ditumpuk ke file utils yang ada. + +4. **Selalu buat file baru** jika implementasi baru tidak secara alami masuk + ke salah satu file yang sudah ada. + +5. **Periksa ukuran file saat ini** sebelum mengedit — jika sudah > 80% dari + batas, sarankan pecah terlebih dahulu. + +--- + +## Pengecualian + +File berikut **dikecualikan** dari aturan batas ukuran: + +- `*.generated.ts` — file hasil code generation (Prisma, tRPC, dll) +- `*.migration.ts` / `*_migration.sql` — file migrasi database +- `*.seed.ts` — file seeding data +- File di folder `__fixtures__/` atau `__mocks__/` + +Pengecualian **tidak berlaku** untuk file konfigurasi runtime seperti +`elysia.config.ts`, `app.ts`, atau `server.ts` — file ini tetap harus ringkas. + +--- + +*Letakkan file ini di root project atau sertakan referensinya di `CLAUDE.md`.* \ No newline at end of file diff --git a/lib/api.ts b/lib/api.ts index a2a84f0..1c7b7a0 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -1,880 +1 @@ -import axios, { AxiosError } from 'axios'; -import Constants from 'expo-constants'; -import { logError } from '@/lib/errorLogger'; - -const api = axios.create({ - baseURL: Constants?.expoConfig?.extra?.URL_API -}); - -api.interceptors.response.use( - (response) => response, - (error: AxiosError) => { - const status = error.response?.status; - const url = error.config?.url ?? 'unknown endpoint'; - const description = `API error ${status ?? 'network'} on ${url}`; - logError(description, error); - return Promise.reject(error); - } -); - -export const apiCheckPhoneLogin = async (body: { phone: string }) => { - const response = await api.post('/auth/login', body) - return response.data; -} - -export const apiSendOtp = async (body: { phone: string, otp: number }) => { - const message = "Desa+\nMasukkan kode ini " + body.otp + " pada aplikasi Desa+ anda. Jangan berikan pada siapapun." - const textFix = encodeURIComponent(message) - const res = await fetch( - `${Constants.expoConfig?.extra?.URL_OTP}/api/wa/send-text`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${Constants.expoConfig?.extra?.WA_SERVER_TOKEN}`, - }, - body: JSON.stringify({ - number: body.phone, - text: message - }) - } - ); - - return res.status -} - -export const apiGetProfile = async ({ id }: { id: string }) => { - const response = await api.get(`mobile/user/${id}`); - return response.data; -}; - -export const apiEditProfile = async (data: FormData) => { - const response = await api.put(`/mobile/user/profile`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - -export const apiGetSearch = async ({ text, user }: { text: string, user: string }) => { - const response = await api.get(`mobile/home/search?search=${text}&user=${user}`); - return response.data; -}; - -export const apiGetBanner = async ({ user }: { user: string }) => { - const response = await api.get(`mobile/banner?user=${user}`); - return response.data; -}; - -export const apiCreateBanner = async (data: FormData) => { - const response = await api.post('mobile/banner', data, - { - headers: { - 'Content-Type': 'multipart/form-data', - }, - } - ) - return response.data; -}; - -export const apiDeleteBanner = async (data: { user: string }, id: string) => { - const response = await api.delete(`mobile/banner/${id}`, { data }) - return response.data; -}; - -export const apiGetBannerOne = async ({ user, id }: { user: string, id: string }) => { - const response = await api.get(`mobile/banner/${id}?user=${user}`); - return response.data; -}; - -export const apiEditBanner = async (data: FormData, id: string) => { - const response = await api.put(`mobile/banner/${id}`, data, - { - headers: { - 'Content-Type': 'multipart/form-data', - }, - } - ) - return response.data; -}; - - -export const apiGetDataHome = async ({ cat, user }: { cat: 'kegiatan' | 'division' | 'progress' | 'dokumen' | 'event' | 'discussion' | 'header' | 'check-late-project', user: string }) => { - const response = await api.get(`mobile/home?user=${user}&cat=${cat}`); - return response.data; -}; - -export const apiGetGroup = async ({ user, active, search }: { user: string, active: string, search: string }) => { - const response = await api.get(`mobile/group?user=${user}&active=${active}&search=${search}`); - return response.data; -}; - -export const apiCreateGroup = async (data: { user: string, name: string }) => { - const response = await api.post('mobile/group', data); - return response.data; -}; - -export const apiEditGroup = async (data: { user: string, name: string }, id: string) => { - const response = await api.put(`mobile/group/${id}`, data); - return response.data; -}; - -export const apiDeleteGroup = async (data: { user: string, isActive: boolean }, id: string) => { - const response = await api.delete(`mobile/group/${id}`, { data }); - return response.data; -}; - -export const apiGetPosition = async ({ user, active, search, group }: { user: string, active: string, search: string, group?: string }) => { - const response = await api.get(`mobile/position?user=${user}&active=${active}&group=${group}&search=${search}`); - return response.data; -}; - -export const apiCreatePosition = async (data: { user: string, name: string, idGroup: string }) => { - const response = await api.post('mobile/position', data); - return response.data; -}; - - -export const apiDeletePosition = async (data: { user: string, isActive: boolean }, id: string) => { - const response = await api.delete(`mobile/position/${id}`, { data }); - return response.data; -}; - -export const apiEditPosition = async (data: { user: string, name: string, idGroup: string }, id: string) => { - const response = await api.put(`mobile/position/${id}`, data) - return response.data -}; - -export const apiGetUser = async ({ user, active, search, group, page }: { user: string, active: string, search: string, group?: string, page?: number }) => { - const response = await api.get(`mobile/user?user=${user}&active=${active}&group=${group}&search=${search}&page=${page}`); - return response.data; -}; - - -export const apiCreateUser = async ({ data }: { data: FormData }) => { - const response = await api.post('/mobile/user', data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - -export const apiDeleteUser = async (data: { user: string, isActive: boolean }, id: string) => { - const response = await api.delete(`mobile/user/${id}`, { data }) - return response.data -}; - -export const apiToggleApprover = async (data: { user: string, isApprover: boolean }, id: string) => { - const response = await api.patch(`mobile/user/${id}`, data) - return response.data -}; - -export const apiEditUser = async (data: FormData, id: string) => { - const response = await api.put(`/mobile/user/${id}`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - -export const apiGetDiscussionGeneral = async ({ user, active, search, group, page }: { user: string, active: string, search: string, group?: string, page?: number }) => { - const response = await api.get(`mobile/discussion-general?user=${user}&active=${active}&group=${group}&search=${search}&page=${page}`); - return response.data; -}; - -export const apiGetDiscussionGeneralOne = async ({ id, user, cat }: { id: string, user: string, cat: string }) => { - const response = await api.get(`mobile/discussion-general/${id}?user=${user}&cat=${cat}`); - return response.data; -}; - -export const apiSendDiscussionGeneralCommentar = async ({ id, data }: { id: string, data: { desc: string, user: string } }) => { - const response = await api.post(`/mobile/discussion-general/${id}/comment`, data) - return response.data; -}; - -export const apiDeleteDiscussionGeneralCommentar = async ({ id, data }: { id: string, data: { user: string } }) => { - const response = await api.delete(`/mobile/discussion-general/${id}/comment`, { data }) - return response.data; -}; - -export const apiUpdateDiscussionGeneralCommentar = async ({ id, data }: { id: string, data: { desc: string, user: string } }) => { - const response = await api.put(`/mobile/discussion-general/${id}/comment`, data) - return response.data; -}; - - -export const apiDeleteMemberDiscussionGeneral = async (data: { user: string, idUser: string }, id: string) => { - const response = await api.delete(`mobile/discussion-general/${id}/member`, { data }); - return response.data; -}; - - -export const apiUpdateStatusDiscussionGeneral = async ({ id, data }: { id: string, data: { status: number, user: string } }) => { - const response = await api.post(`/mobile/discussion-general/${id}`, data) - return response.data; -}; - -export const apiDeleteDiscussionGeneral = async (data: { user: string, active: boolean }, id: string) => { - const response = await api.delete(`mobile/discussion-general/${id}`, { data }); - return response.data; -}; - -export const apiEditDiscussionGeneral = async (data: FormData, id: string) => { - const response = await api.put(`/mobile/discussion-general/${id}`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - -// export const apiCreateDiscussionGeneral = async ({ data }: { data: { idGroup: string, title: string, desc: string, user: string, member: [] } }) => { -// const response = await api.post(`/mobile/discussion-general`, data) -// return response.data; -// }; - -export const apiCreateDiscussionGeneral = async (data: FormData) => { - // const response = await api.post(`/mobile/discussion-general`, data) - const response = await api.post(`/mobile/discussion-general`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - - -export const apiAddMemberDiscussionGeneral = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => { - const response = await api.post(`/mobile/discussion-general/${id}/member`, data) - return response.data; -}; - -export const apiGetAnnouncement = async ({ user, search, page }: { user: string, search: string, page?: number }) => { - const response = await api.get(`mobile/announcement?user=${user}&search=${search}&page=${page}`); - return response.data; -}; - -export const apiGetDivisionGroup = async ({ user }: { user: string }) => { - const response = await api.get(`mobile/group/get-division?user=${user}`); - return response.data; -}; - -// export const apiCreateAnnouncement = async ({ data }: { data: { title: string, desc: string, user: string, groups: any[] } }) => { -// const response = await api.post(`/mobile/announcement`, data) -// return response.data; -// }; - -export const apiCreateAnnouncement = async (data: FormData) => { - const response = await api.post(`/mobile/announcement`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - - -export const apiGetAnnouncementOne = async ({ user, id }: { user: string, id: string }) => { - const response = await api.get(`mobile/announcement/${id}?user=${user}`); - return response.data; -}; - -// export const apiEditAnnouncement = async (data: { title: string, desc: string, user: string, groups: any[], oldFile: any[] }, id: string) => { -// const response = await api.put(`/mobile/announcement/${id}`, data) -// return response.data; -// }; - -export const apiEditAnnouncement = async (data: FormData, id: string) => { - const response = await api.put(`/mobile/announcement/${id}`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - - -export const apiDeleteAnnouncement = async (data: { user: string }, id: string) => { - const response = await api.delete(`mobile/announcement/${id}`, { data }) - return response.data -}; - -export const apiGetTahunProject = async ({ user }: { user: string }) => { - const response = await api.get(`mobile/project/tahun?user=${user}`); - return response.data; -}; - -export const apiGetProject = async ({ user, status, search, group, kategori, page, year }: { user: string, status: string, search: string, group?: string, kategori?: string, page?: number, year?: string }) => { - const response = await api.get(`mobile/project?user=${user}&status=${status}&group=${group}&search=${search}&cat=${kategori}&page=${page}&year=${year}`); - return response.data; -}; - -export const apiGetProjectOne = async ({ user, cat, id }: { user: string, cat: 'data' | 'progress' | 'task' | 'file' | 'member' | 'link', id: string }) => { - const response = await api.get(`mobile/project/${id}?user=${user}&cat=${cat}`); - return response.data; -}; - -export const apiEditProject = async (data: { name: string, user: string }, id: string) => { - const response = await api.put(`/mobile/project/${id}`, data) - return response.data; -}; - -export const apiReportProject = async (data: { report: string, user: string }, id: string) => { - const response = await api.put(`/mobile/project/${id}/lainnya`, data) - return response.data; -}; - -export const apiCreateProjectTask = async ({ data, id }: { data: { name: string, dateStart: string, user: string, dateEnd: string, dataDetail: any[] }, id: string }) => { - const response = await api.post(`/mobile/project/${id}`, data) - return response.data; -}; - -export const apiCancelProject = async (data: { user: string, reason: string }, id: string) => { - const response = await api.delete(`mobile/project/${id}`, { data }) - return response.data -}; - -export const apiUpdateStatusProjectTask = async (data: { user: string, status: number, idProject: string }, id: string) => { - const response = await api.put(`mobile/project/detail/${id}`, data) - return response.data -}; - -export const apiDeleteProjectTask = async (data: { user: string, idProject: string }, id: string) => { - const response = await api.delete(`mobile/project/detail/${id}`, { data }) - return response.data -}; - -export const apiGetProjectTask = async ({ user, id, cat }: { user: string, id: string, cat?: string }) => { - const response = await api.get(`mobile/project/detail/${id}?user=${user}${cat ? `&cat=${cat}` : ""}`); - return response.data; -}; - -export const apiEditProjectTask = async ({ data, id }: { data: { title: string, dateStart: string, user: string, dateEnd: string, dataDetail: any[] }, id: string }) => { - const response = await api.post(`/mobile/project/detail/${id}`, data) - return response.data; -}; - -export const apiDeleteProjectMember = async (data: { user: string, idUser: string }, id: string) => { - const response = await api.delete(`mobile/project/${id}/member`, { data }) - return response.data -}; - -export const apiGetProjectTaskFile = async ({ user, id }: { user: string, id: string }) => { - const response = await api.get(`/mobile/project/task/file/${id}`, { params: { user } }) - return response.data; -}; - -export const apiAddProjectTaskFile = async ({ data, id }: { data: FormData, id: string }) => { - const response = await api.post(`/mobile/project/task/file/${id}`, data, { - headers: { 'Content-Type': 'multipart/form-data' }, - }) - return response.data; -}; - -export const apiLinkProjectTaskFile = async ({ user, idFile, id }: { user: string, idFile: string, id: string }) => { - const response = await api.patch(`/mobile/project/task/file/${id}`, { user, idFile }) - return response.data; -}; - -export const apiDeleteProjectTaskFile = async (data: { user: string }, id: string) => { - const response = await api.delete(`/mobile/project/task/file/${id}`, { data }) - return response.data; -}; - -export const apiGetProjectTaskApprovals = async ({ user, id }: { user: string, id: string }) => { - const response = await api.get(`/mobile/project/task/${id}/approval`, { params: { user } }) - return response.data; -}; - -export const apiSubmitProjectTask = async ({ user, id }: { user: string, id: string }) => { - const response = await api.post(`/mobile/project/task/${id}/approval`, { user }) - return response.data; -}; - -export const apiApproveRejectProjectTask = async ({ user, id, action, note }: { user: string, id: string, action: 'approve' | 'reject', note?: string }) => { - const response = await api.put(`/mobile/project/task/${id}/approval`, { user, action, note }) - return response.data; -}; - - -export const apiAddMemberProject = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => { - const response = await api.post(`/mobile/project/${id}/member`, data) - return response.data; -}; - -export const apiCreateProject = async (data: FormData) => { - const response = await api.post(`/mobile/project`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - -export const apiDeleteProject = async (data: { user: string }, id: string) => { - const response = await api.delete(`/mobile/project/${id}/lainnya`, { data }) - return response.data; -}; - -export const apiAddLinkProject = async (data: { user: string, link: string }, id: string) => { - const response = await api.post(`/mobile/project/${id}/link`, data) - return response.data; -}; - -export const apiAddFileProject = async ({ data, id }: { data: FormData, id: string }) => { - const response = await api.post(`/mobile/project/file/${id}`, data, - { - headers: { - 'Content-Type': 'multipart/form-data', - }, - } - ) - return response.data; -}; - -export const apiCheckFileProject = async ({ data, id }: { data: FormData, id: string }) => { - const response = await api.put(`/mobile/project/file/${id}`, data, - { - headers: { - 'Content-Type': 'multipart/form-data', - }, - } - ) - return response.data; -}; - -export const apiDeleteFileProject = async (data: { user: string }, id: string) => { - const response = await api.delete(`/mobile/project/file/${id}`, { data }) - return response.data; -}; - -export const apiDeleteLinkProject = async (data: { idLink: string, user: string }, id: string) => { - const response = await api.delete(`/mobile/project/${id}/link`, { data }) - return response.data; -}; - -export const apiGetDivision = async ({ user, search, group, kategori, active, page }: { user: string, search: string, group?: string, kategori?: string, active?: string, page?: number }) => { - const response = await api.get(`mobile/division?user=${user}&active=${active}&group=${group}&search=${search}&cat=${kategori}&page=${page}`); - return response.data; -}; - -export const apiGetDivisionReport = async ({ user, cat, date, dateEnd, division, group }: { user: string, cat: 'table-progress' | 'lainnya', date: string, dateEnd: string, division: string, group?: string }) => { - const response = await api.get(`mobile/division/report?user=${user}&cat=${cat}&date=${date}&date-end=${dateEnd}&division=${division}&group=${group}`); - return response.data; -}; - -export const apiGetDivisionOneFeature = async ({ user, cat, id }: { user: string, cat: 'jumlah' | 'today-task' | 'new-file' | 'new-discussion' | 'check-member' | 'check-admin', id: string }) => { - const response = await api.get(`mobile/division/${id}/detail?user=${user}&cat=${cat}`); - return response.data; -}; - -export const apiGetDivisionOneDetail = async ({ user, id }: { user: string, id: string }) => { - const response = await api.get(`mobile/division/${id}?user=${user}`); - return response.data; -}; - -export const apiUpdateStatusAdminDivision = async (data: { user: string, id: string, isAdmin: boolean }, id: string) => { - const response = await api.put(`mobile/division/${id}/detail`, data) - return response.data -}; - -export const apiDeleteMemberDivision = async (data: { user: string, id: string }, id: string) => { - const response = await api.delete(`/mobile/division/${id}/detail`, { data }) - return response.data; -}; - -export const apiAddMemberDivision = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => { - const response = await api.post(`/mobile/division/${id}/detail`, data) - return response.data; -}; - -export const apiEditDivision = async (data: { user: string, name: string, desc: string }, id: string) => { - const response = await api.put(`mobile/division/${id}`, data) - return response.data -}; - -export const apiUpdateStatusDivision = async ({ data, id }: { data: { user: string, isActive: boolean }, id: string }) => { - const response = await api.post(`/mobile/division/${id}/status`, data) - return response.data; -}; - -export const apiGetDivisionMember = async ({ user, id, search }: { user: string, id: string, search: string }) => { - const response = await api.get(`mobile/division/${id}/member?user=${user}&search=${search}`); - return response.data; -}; - -export const apiGetListDivisionByIdDivision = async ({ user, search, division }: { user: string, search: string, division: string }) => { - const response = await api.get(`mobile/division/more?user=${user}&search=${search}&division=${division}`); - return response.data; -}; - -export const apiCreateDivision = async (data: { data: { idGroup: string, name: string, desc: string }, member: [], admin: string[], user: string }) => { - const response = await api.post(`/mobile/division`, data) - return response.data; -}; - -export const apiCheckDivisionName = async (data: { data: { idGroup: string, name: string, desc: string }, user: string }) => { - const response = await api.put(`/mobile/division`, data) - return response.data; -}; - -export const apiGetDiscussion = async ({ user, search, division, active, page }: { user: string, search: string, division: string, active?: string, page?: number }) => { - const response = await api.get(`mobile/discussion?user=${user}&active=${active}&search=${search}&division=${division}&page=${page}`); - return response.data; -}; - -export const apiGetDiscussionOne = async ({ id, user, cat }: { id: string, user: string, cat: 'data' | 'comment' | 'file' }) => { - const response = await api.get(`mobile/discussion/${id}?user=${user}&cat=${cat}`); - return response.data; -}; - -export const apiSendDiscussionCommentar = async ({ data, id }: { data: { user: string, comment: string }, id: string }) => { - const response = await api.post(`/mobile/discussion/${id}/comment`, data) - return response.data; -}; - -export const apiEditDiscussionCommentar = async ({ data, id }: { data: { user: string, comment: string }, id: string }) => { - const response = await api.put(`/mobile/discussion/${id}/comment`, data) - return response.data; -}; - -export const apiDeleteDiscussionCommentar = async ({ data, id }: { data: { user: string }, id: string }) => { - const response = await api.delete(`/mobile/discussion/${id}/comment`, { data }) - return response.data; -}; - -// export const apiEditDiscussion = async ({ data, id }: { data: { user: string, desc: string }, id: string }) => { -// const response = await api.post(`/mobile/discussion/${id}`, data) -// return response.data; -// }; - -export const apiEditDiscussion = async (data: FormData, id: string) => { - const response = await api.post(`/mobile/discussion/${id}`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - -export const apiArchiveDiscussion = async (data: { user: string, active: boolean }, id: string) => { - const response = await api.put(`mobile/discussion/${id}`, data) - return response.data -}; - -export const apiOpenCloseDiscussion = async (data: { user: string, status: number }, id: string) => { - const response = await api.delete(`mobile/discussion/${id}`, { data }) - return response.data -}; - -// export const apiCreateDiscussion = async ({ data }: { data: { user: string, desc: string, idDivision: string } }) => { -// const response = await api.post(`/mobile/discussion`, data) -// return response.data; -// }; - -export const apiCreateDiscussion = async (data: FormData) => { - const response = await api.post(`/mobile/discussion`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - -export const apiGetCalendarByDateDivision = async ({ user, date, division }: { user: string, date: string, division: string, }) => { - const response = await api.get(`mobile/calendar?user=${user}&date=${date}&division=${division}`); - return response.data; -}; - -export const apiGetIndicatorCalendar = async ({ user, date, division }: { user: string, date: string, division: string, }) => { - const response = await api.get(`mobile/calendar/indicator?user=${user}&date=${date}&division=${division}`); - return response.data; -}; - -export const apiGetCalendarOne = async ({ user, id, cat }: { user: string, id: string, cat: 'data' | 'member' }) => { - const response = await api.get(`mobile/calendar/${id}?user=${user}&cat=${cat}`); - return response.data; -}; - -export const apiDeleteCalendarMember = async (data: { user: string, idUser: string }, id: string) => { - const response = await api.delete(`/mobile/calendar/${id}/member`, { data }) - return response.data -}; - -export const apiAddMemberCalendar = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => { - const response = await api.post(`/mobile/calendar/${id}/member`, data) - return response.data; -}; - -export const apiDeleteCalendar = async (data: { user: string }, id: string) => { - const response = await api.delete(`/mobile/calendar/${id}`, { data }) - return response.data -}; - -export const apiGetCalendarHistory = async ({ user, search, division, page }: { user: string, search: string, division: string, page?: number }) => { - const response = await api.get(`mobile/calendar/history?user=${user}&search=${search}&division=${division}&page=${page}`); - return response.data; -}; - -export const apiGetVillageCalendarByDate = async ({ user, date }: { user: string, date: string }) => { - const response = await api.get(`mobile/village-calendar?user=${user}&date=${date}`); - return response.data; -}; - -export const apiGetVillageCalendarIndicator = async ({ user, date }: { user: string, date: string }) => { - const response = await api.get(`mobile/village-calendar/indicator?user=${user}&date=${date}`); - return response.data; -}; - -export const apiCreateCalendar = async ({ data }: { data: { idDivision: string, title: string, desc: string, timeStart: string, timeEnd: string, dateStart: string, repeatEventTyper: string, repeatValue: string, linkMeet: string, member: any[], user: string } }) => { - const response = await api.post(`/mobile/calendar`, data) - return response.data; -}; - -export const apiUpdateCalendar = async ({ data, id }: { data: { title: string, desc: string, timeStart: string, timeEnd: string, dateStart: string, repeatEventTyper: string, repeatValue: number, linkMeet: string, user: string }, id: string }) => { - const response = await api.put(`/mobile/calendar/${id}`, data) - return response.data; -}; - -export const apiGetTask = async ({ user, status, search, division, page, year }: { user: string, status: string, search: string, division: string, page?: number, year?: string }) => { - const response = await api.get(`mobile/task?user=${user}&status=${status}&division=${division}&search=${search}&page=${page}&year=${year}`); - return response.data; -}; - -export const apiGetTahunTask = async ({ user, division }: { user: string, division: string }) => { - const response = await api.get(`mobile/task/tahun?user=${user}&division=${division}`); - return response.data; -}; - -export const apiGetTaskOne = async ({ user, cat, id }: { user: string, cat: 'data' | 'progress' | 'task' | 'file' | 'member' | 'link', id: string }) => { - const response = await api.get(`mobile/task/${id}?user=${user}&cat=${cat}`); - return response.data; -}; - -export const apiUpdateStatusTaskDivision = async (data: { user: string, status: number, idProject: string }, id: string) => { - const response = await api.put(`mobile/task/detail/${id}`, data) - return response.data -}; - -export const apiGetTaskTugas = async ({ user, id, cat }: { user: string, id: string, cat?: string }) => { - const response = await api.get(`mobile/task/detail/${id}?user=${user}${cat ? `&cat=${cat}` : ""}`); - return response.data; -}; - -export const apiEditTaskTugas = async ({ data, id }: { data: { title: string, dateStart: string, user: string, dateEnd: string, dataDetail: any[] }, id: string }) => { - const response = await api.post(`/mobile/task/detail/${id}`, data) - return response.data; -}; - -export const apiDeleteTaskTugas = async (data: { user: string, idProject: string }, id: string) => { - const response = await api.delete(`mobile/task/detail/${id}`, { data }) - return response.data -}; - -export const apiDeleteFileTask = async (data: { user: string }, id: string) => { - const response = await api.delete(`/mobile/task/file/${id}`, { data }) - return response.data; -}; - -export const apiDeleteLinkTask = async (data: { user: string, idLink: string }, id: string) => { - const response = await api.delete(`/mobile/task/${id}/link`, { data }) - return response.data; -}; - -export const apiDeleteTaskMember = async (data: { user: string, idUser: string }, id: string) => { - const response = await api.delete(`mobile/task/${id}/member`, { data }) - return response.data -}; - -export const apiCreateTaskTugas = async ({ data, id }: { data: { title: string, dateStart: string, user: string, dateEnd: string, idDivision: string, dataDetail: any[] }, id: string }) => { - const response = await api.post(`/mobile/task/${id}`, data) - return response.data; -}; - -export const apiCheckFileTask = async ({ data, id }: { data: FormData, id: string }) => { - const response = await api.put(`/mobile/task/file/${id}`, data, - { - headers: { - 'Content-Type': 'multipart/form-data', - }, - } - ) - return response.data; -}; - -export const apiAddFileTask = async ({ data, id }: { data: FormData, id: string }) => { - const response = await api.post(`/mobile/task/file/${id}`, data, - { - headers: { - 'Content-Type': 'multipart/form-data', - }, - } - ) - return response.data; -}; - -export const apiGetTaskTugasApprovals = async ({ user, id }: { user: string, id: string }) => { - const response = await api.get(`/mobile/task/tugas/${id}/approval`, { params: { user } }) - return response.data; -}; - -export const apiSubmitTaskTugas = async ({ user, id }: { user: string, id: string }) => { - const response = await api.post(`/mobile/task/tugas/${id}/approval`, { user }) - return response.data; -}; - -export const apiApproveRejectTaskTugas = async ({ user, id, action, note }: { user: string, id: string, action: 'approve' | 'reject', note?: string }) => { - const response = await api.put(`/mobile/task/tugas/${id}/approval`, { user, action, note }) - return response.data; -}; - -export const apiGetTugasTaskFile = async ({ user, id }: { user: string, id: string }) => { - const response = await api.get(`/mobile/task/tugas/file/${id}`, { params: { user } }) - return response.data; -}; - -export const apiAddTugasTaskFile = async ({ data, id }: { data: FormData, id: string }) => { - const response = await api.post(`/mobile/task/tugas/file/${id}`, data, { - headers: { 'Content-Type': 'multipart/form-data' }, - }) - return response.data; -}; - -export const apiLinkTugasTaskFile = async ({ user, idFile, id }: { user: string, idFile: string, id: string }) => { - const response = await api.patch(`/mobile/task/tugas/file/${id}`, { user, idFile }) - return response.data; -}; - -export const apiDeleteTugasTaskFile = async (data: { user: string }, id: string) => { - const response = await api.delete(`/mobile/task/tugas/file/${id}`, { data }) - return response.data; -}; - -export const apiEditTask = async (data: { title: string, user: string }, id: string) => { - const response = await api.put(`/mobile/task/${id}`, data) - return response.data; -}; - -export const apiReportTask = async (data: { report: string, user: string }, id: string) => { - const response = await api.put(`/mobile/task/${id}/lainnya`, data) - return response.data; -}; - -export const apiCancelTask = async (data: { user: string, reason: string }, id: string) => { - const response = await api.delete(`mobile/task/${id}`, { data }) - return response.data -}; - -export const apiAddMemberTask = async ({ data, id }: { data: { user: string, member: any[], idDivision: string }, id: string }) => { - const response = await api.post(`/mobile/task/${id}/member`, data) - return response.data; -}; - -export const apiCreateTask = async (data: FormData) => { - const response = await api.post(`/mobile/task`, data, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - return response.data; -}; - -export const apiDeleteTask = async (data: { user: string }, id: string) => { - const response = await api.delete(`/mobile/task/${id}/lainnya`, { data }) - return response.data; -}; - -export const apiAddLinkTask = async (data: { user: string, link: string, idDivision: string }, id: string) => { - const response = await api.post(`/mobile/task/${id}/link`, data) - return response.data; -}; - -export const apiGetDocument = async ({ user, path, division, category }: { user: string, path: string, division: string, category: 'all' | 'folder' }) => { - const response = await api.get(`mobile/document?user=${user}&path=${path}&division=${division}&category=${category}`); - return response.data; -}; - -export const apiGetDocumentInformasi = async ({ user, item, cat }: { user: string, item: string, cat: 'share' | 'lainnya' }) => { - const response = await api.get(`mobile/document/more?user=${user}&item=${item}&cat=${cat}`); - return response.data; -}; - -export const apiDocumentRename = async (data: { name: string, user: string, id: string, path: string, idDivision: string, extension: string }) => { - const response = await api.put(`/mobile/document`, data) - return response.data; -}; - -export const apiDocumentDelete = async (data: { user: string, data: any[] }) => { - const response = await api.delete(`/mobile/document`, { data }) - return response.data -}; - -export const apiCreateFolderDocument = async ({ data }: { data: { name: string, path: string, idDivision: string, user: string } }) => { - const response = await api.post(`/mobile/document`, data) - return response.data; -}; - -export const apiUploadFileDocument = async ({ data }: { data: FormData }) => { - const response = await api.post(`/mobile/document/upload`, data, - { - headers: { - 'Content-Type': 'multipart/form-data', - }, - } - ) - return response.data; -}; - -export const apiMoveDocument = async (data: { path: string, dataItem: any[], user: string }) => { - const response = await api.post(`/mobile/document/more`, data) - return response.data; -}; - -export const apiCopyDocument = async (data: { path: string, dataItem: any[], user: string, idDivision: string }) => { - const response = await api.put(`/mobile/document/more`, data) - return response.data; -}; - - -export const apiShareDocument = async (data: { dataDivision: any[], dataItem: any[], user: string }) => { - const response = await api.delete(`/mobile/document/more`, { data }) - return response.data; -}; - -export const apiRegisteredToken = async (data: { user: string, token: string, category?: string }) => { - const response = await api.post(`/mobile/auth-token`, data) - return response.data; -}; - -export const apiUnregisteredToken = async (data: { user: string, token: string, category?: string }) => { - const response = await api.put(`/mobile/auth-token`, data) - return response.data; -}; - -export const apiGetCheckToken = async (data: { user: string, token: string }) => { - const response = await api.post(`mobile/auth-token/check`, data); - return response.data; -}; - -export const apiGetNotification = async ({ user, page }: { user: string, page?: number }) => { - const response = await api.get(`mobile/home/notification?user=${user}&page=${page}`); - return response.data; -}; - -export const apiReadOneNotification = async (data: { user: string, id: string }) => { - const response = await api.put(`/mobile/home/notification`, data) - return response.data; -}; - -export const apiReadAllNotification = async (data: { user: string }) => { - const response = await api.post(`/mobile/home/notification`, data) - return response.data; -}; - -export const apiGetVersion = async () => { - const response = await api.get(`mobile/version`); - return response.data; -}; \ No newline at end of file +export * from './api/index'; diff --git a/lib/api/announcement.api.ts b/lib/api/announcement.api.ts new file mode 100644 index 0000000..1cc0341 --- /dev/null +++ b/lib/api/announcement.api.ts @@ -0,0 +1,30 @@ +import api from './client'; + +export const apiGetAnnouncement = async ({ user, search, page }: { user: string, search: string, page?: number }) => { + const response = await api.get(`mobile/announcement?user=${user}&search=${search}&page=${page}`); + return response.data; +}; + +export const apiCreateAnnouncement = async (data: FormData) => { + const response = await api.post(`/mobile/announcement`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiGetAnnouncementOne = async ({ user, id }: { user: string, id: string }) => { + const response = await api.get(`mobile/announcement/${id}?user=${user}`); + return response.data; +}; + +export const apiEditAnnouncement = async (data: FormData, id: string) => { + const response = await api.put(`/mobile/announcement/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiDeleteAnnouncement = async (data: { user: string }, id: string) => { + const response = await api.delete(`mobile/announcement/${id}`, { data }) + return response.data +}; diff --git a/lib/api/auth.api.ts b/lib/api/auth.api.ts new file mode 100644 index 0000000..991a3b3 --- /dev/null +++ b/lib/api/auth.api.ts @@ -0,0 +1,46 @@ +import Constants from 'expo-constants'; +import api from './client'; + +export const apiCheckPhoneLogin = async (body: { phone: string }) => { + const response = await api.post('/auth/login', body) + return response.data; +} + +export const apiSendOtp = async (body: { phone: string, otp: number }) => { + const message = "Desa+\nMasukkan kode ini " + body.otp + " pada aplikasi Desa+ anda. Jangan berikan pada siapapun." + const res = await fetch( + `${Constants.expoConfig?.extra?.URL_OTP}/api/wa/send-text`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${Constants.expoConfig?.extra?.WA_SERVER_TOKEN}`, + }, + body: JSON.stringify({ + number: body.phone, + text: message + }) + } + ); + return res.status +} + +export const apiRegisteredToken = async (data: { user: string, token: string, category?: string }) => { + const response = await api.post(`/mobile/auth-token`, data) + return response.data; +}; + +export const apiUnregisteredToken = async (data: { user: string, token: string, category?: string }) => { + const response = await api.put(`/mobile/auth-token`, data) + return response.data; +}; + +export const apiGetCheckToken = async (data: { user: string, token: string }) => { + const response = await api.post(`mobile/auth-token/check`, data); + return response.data; +}; + +export const apiGetVersion = async () => { + const response = await api.get(`mobile/version`); + return response.data; +}; diff --git a/lib/api/banner.api.ts b/lib/api/banner.api.ts new file mode 100644 index 0000000..3789853 --- /dev/null +++ b/lib/api/banner.api.ts @@ -0,0 +1,30 @@ +import api from './client'; + +export const apiGetBanner = async ({ user }: { user: string }) => { + const response = await api.get(`mobile/banner?user=${user}`); + return response.data; +}; + +export const apiCreateBanner = async (data: FormData) => { + const response = await api.post('mobile/banner', data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiDeleteBanner = async (data: { user: string }, id: string) => { + const response = await api.delete(`mobile/banner/${id}`, { data }) + return response.data; +}; + +export const apiGetBannerOne = async ({ user, id }: { user: string, id: string }) => { + const response = await api.get(`mobile/banner/${id}?user=${user}`); + return response.data; +}; + +export const apiEditBanner = async (data: FormData, id: string) => { + const response = await api.put(`mobile/banner/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; diff --git a/lib/api/calendar.api.ts b/lib/api/calendar.api.ts new file mode 100644 index 0000000..66a7209 --- /dev/null +++ b/lib/api/calendar.api.ts @@ -0,0 +1,56 @@ +import api from './client'; + +export const apiGetCalendarByDateDivision = async ({ user, date, division }: { user: string, date: string, division: string }) => { + const response = await api.get(`mobile/calendar?user=${user}&date=${date}&division=${division}`); + return response.data; +}; + +export const apiGetIndicatorCalendar = async ({ user, date, division }: { user: string, date: string, division: string }) => { + const response = await api.get(`mobile/calendar/indicator?user=${user}&date=${date}&division=${division}`); + return response.data; +}; + +export const apiGetCalendarOne = async ({ user, id, cat }: { user: string, id: string, cat: 'data' | 'member' }) => { + const response = await api.get(`mobile/calendar/${id}?user=${user}&cat=${cat}`); + return response.data; +}; + +export const apiGetCalendarHistory = async ({ user, search, division, page }: { user: string, search: string, division: string, page?: number }) => { + const response = await api.get(`mobile/calendar/history?user=${user}&search=${search}&division=${division}&page=${page}`); + return response.data; +}; + +export const apiCreateCalendar = async ({ data }: { data: { idDivision: string, title: string, desc: string, timeStart: string, timeEnd: string, dateStart: string, repeatEventTyper: string, repeatValue: string, linkMeet: string, member: any[], user: string } }) => { + const response = await api.post(`/mobile/calendar`, data) + return response.data; +}; + +export const apiUpdateCalendar = async ({ data, id }: { data: { title: string, desc: string, timeStart: string, timeEnd: string, dateStart: string, repeatEventTyper: string, repeatValue: number, linkMeet: string, user: string }, id: string }) => { + const response = await api.put(`/mobile/calendar/${id}`, data) + return response.data; +}; + +export const apiDeleteCalendar = async (data: { user: string }, id: string) => { + const response = await api.delete(`/mobile/calendar/${id}`, { data }) + return response.data +}; + +export const apiAddMemberCalendar = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => { + const response = await api.post(`/mobile/calendar/${id}/member`, data) + return response.data; +}; + +export const apiDeleteCalendarMember = async (data: { user: string, idUser: string }, id: string) => { + const response = await api.delete(`/mobile/calendar/${id}/member`, { data }) + return response.data +}; + +export const apiGetVillageCalendarByDate = async ({ user, date }: { user: string, date: string }) => { + const response = await api.get(`mobile/village-calendar?user=${user}&date=${date}`); + return response.data; +}; + +export const apiGetVillageCalendarIndicator = async ({ user, date }: { user: string, date: string }) => { + const response = await api.get(`mobile/village-calendar/indicator?user=${user}&date=${date}`); + return response.data; +}; diff --git a/lib/api/client.ts b/lib/api/client.ts new file mode 100644 index 0000000..4ecee1e --- /dev/null +++ b/lib/api/client.ts @@ -0,0 +1,20 @@ +import axios, { AxiosError } from 'axios'; +import Constants from 'expo-constants'; +import { logError } from '@/lib/errorLogger'; + +const api = axios.create({ + baseURL: Constants?.expoConfig?.extra?.URL_API +}); + +api.interceptors.response.use( + (response) => response, + (error: AxiosError) => { + const status = error.response?.status; + const url = error.config?.url ?? 'unknown endpoint'; + const description = `API error ${status ?? 'network'} on ${url}`; + logError(description, error); + return Promise.reject(error); + } +); + +export default api; diff --git a/lib/api/discussion.api.ts b/lib/api/discussion.api.ts new file mode 100644 index 0000000..ef178af --- /dev/null +++ b/lib/api/discussion.api.ts @@ -0,0 +1,109 @@ +import api from './client'; + +export const apiGetDiscussionGeneral = async ({ user, active, search, group, page }: { user: string, active: string, search: string, group?: string, page?: number }) => { + const response = await api.get(`mobile/discussion-general?user=${user}&active=${active}&group=${group}&search=${search}&page=${page}`); + return response.data; +}; + +export const apiGetDiscussionGeneralOne = async ({ id, user, cat }: { id: string, user: string, cat: string }) => { + const response = await api.get(`mobile/discussion-general/${id}?user=${user}&cat=${cat}`); + return response.data; +}; + +export const apiCreateDiscussionGeneral = async (data: FormData) => { + const response = await api.post(`/mobile/discussion-general`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiEditDiscussionGeneral = async (data: FormData, id: string) => { + const response = await api.put(`/mobile/discussion-general/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiDeleteDiscussionGeneral = async (data: { user: string, active: boolean }, id: string) => { + const response = await api.delete(`mobile/discussion-general/${id}`, { data }); + return response.data; +}; + +export const apiUpdateStatusDiscussionGeneral = async ({ id, data }: { id: string, data: { status: number, user: string } }) => { + const response = await api.post(`/mobile/discussion-general/${id}`, data) + return response.data; +}; + +export const apiSendDiscussionGeneralCommentar = async ({ id, data }: { id: string, data: { desc: string, user: string } }) => { + const response = await api.post(`/mobile/discussion-general/${id}/comment`, data) + return response.data; +}; + +export const apiUpdateDiscussionGeneralCommentar = async ({ id, data }: { id: string, data: { desc: string, user: string } }) => { + const response = await api.put(`/mobile/discussion-general/${id}/comment`, data) + return response.data; +}; + +export const apiDeleteDiscussionGeneralCommentar = async ({ id, data }: { id: string, data: { user: string } }) => { + const response = await api.delete(`/mobile/discussion-general/${id}/comment`, { data }) + return response.data; +}; + +export const apiAddMemberDiscussionGeneral = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => { + const response = await api.post(`/mobile/discussion-general/${id}/member`, data) + return response.data; +}; + +export const apiDeleteMemberDiscussionGeneral = async (data: { user: string, idUser: string }, id: string) => { + const response = await api.delete(`mobile/discussion-general/${id}/member`, { data }); + return response.data; +}; + +export const apiGetDiscussion = async ({ user, search, division, active, page }: { user: string, search: string, division: string, active?: string, page?: number }) => { + const response = await api.get(`mobile/discussion?user=${user}&active=${active}&search=${search}&division=${division}&page=${page}`); + return response.data; +}; + +export const apiGetDiscussionOne = async ({ id, user, cat }: { id: string, user: string, cat: 'data' | 'comment' | 'file' }) => { + const response = await api.get(`mobile/discussion/${id}?user=${user}&cat=${cat}`); + return response.data; +}; + +export const apiCreateDiscussion = async (data: FormData) => { + const response = await api.post(`/mobile/discussion`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiEditDiscussion = async (data: FormData, id: string) => { + const response = await api.post(`/mobile/discussion/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiArchiveDiscussion = async (data: { user: string, active: boolean }, id: string) => { + const response = await api.put(`mobile/discussion/${id}`, data) + return response.data +}; + +export const apiOpenCloseDiscussion = async (data: { user: string, status: number }, id: string) => { + const response = await api.delete(`mobile/discussion/${id}`, { data }) + return response.data +}; + +export const apiSendDiscussionCommentar = async ({ data, id }: { data: { user: string, comment: string }, id: string }) => { + const response = await api.post(`/mobile/discussion/${id}/comment`, data) + return response.data; +}; + +export const apiEditDiscussionCommentar = async ({ data, id }: { data: { user: string, comment: string }, id: string }) => { + const response = await api.put(`/mobile/discussion/${id}/comment`, data) + return response.data; +}; + +export const apiDeleteDiscussionCommentar = async ({ data, id }: { data: { user: string }, id: string }) => { + const response = await api.delete(`/mobile/discussion/${id}/comment`, { data }) + return response.data; +}; diff --git a/lib/api/division.api.ts b/lib/api/division.api.ts new file mode 100644 index 0000000..fc8bc41 --- /dev/null +++ b/lib/api/division.api.ts @@ -0,0 +1,66 @@ +import api from './client'; + +export const apiGetDivision = async ({ user, search, group, kategori, active, page }: { user: string, search: string, group?: string, kategori?: string, active?: string, page?: number }) => { + const response = await api.get(`mobile/division?user=${user}&active=${active}&group=${group}&search=${search}&cat=${kategori}&page=${page}`); + return response.data; +}; + +export const apiGetDivisionReport = async ({ user, cat, date, dateEnd, division, group }: { user: string, cat: 'table-progress' | 'lainnya', date: string, dateEnd: string, division: string, group?: string }) => { + const response = await api.get(`mobile/division/report?user=${user}&cat=${cat}&date=${date}&date-end=${dateEnd}&division=${division}&group=${group}`); + return response.data; +}; + +export const apiGetDivisionOneFeature = async ({ user, cat, id }: { user: string, cat: 'jumlah' | 'today-task' | 'new-file' | 'new-discussion' | 'check-member' | 'check-admin', id: string }) => { + const response = await api.get(`mobile/division/${id}/detail?user=${user}&cat=${cat}`); + return response.data; +}; + +export const apiGetDivisionOneDetail = async ({ user, id }: { user: string, id: string }) => { + const response = await api.get(`mobile/division/${id}?user=${user}`); + return response.data; +}; + +export const apiCreateDivision = async (data: { data: { idGroup: string, name: string, desc: string }, member: [], admin: string[], user: string }) => { + const response = await api.post(`/mobile/division`, data) + return response.data; +}; + +export const apiCheckDivisionName = async (data: { data: { idGroup: string, name: string, desc: string }, user: string }) => { + const response = await api.put(`/mobile/division`, data) + return response.data; +}; + +export const apiEditDivision = async (data: { user: string, name: string, desc: string }, id: string) => { + const response = await api.put(`mobile/division/${id}`, data) + return response.data +}; + +export const apiUpdateStatusDivision = async ({ data, id }: { data: { user: string, isActive: boolean }, id: string }) => { + const response = await api.post(`/mobile/division/${id}/status`, data) + return response.data; +}; + +export const apiGetDivisionMember = async ({ user, id, search }: { user: string, id: string, search: string }) => { + const response = await api.get(`mobile/division/${id}/member?user=${user}&search=${search}`); + return response.data; +}; + +export const apiGetListDivisionByIdDivision = async ({ user, search, division }: { user: string, search: string, division: string }) => { + const response = await api.get(`mobile/division/more?user=${user}&search=${search}&division=${division}`); + return response.data; +}; + +export const apiUpdateStatusAdminDivision = async (data: { user: string, id: string, isAdmin: boolean }, id: string) => { + const response = await api.put(`mobile/division/${id}/detail`, data) + return response.data +}; + +export const apiDeleteMemberDivision = async (data: { user: string, id: string }, id: string) => { + const response = await api.delete(`/mobile/division/${id}/detail`, { data }) + return response.data; +}; + +export const apiAddMemberDivision = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => { + const response = await api.post(`/mobile/division/${id}/detail`, data) + return response.data; +}; diff --git a/lib/api/document.api.ts b/lib/api/document.api.ts new file mode 100644 index 0000000..139422a --- /dev/null +++ b/lib/api/document.api.ts @@ -0,0 +1,48 @@ +import api from './client'; + +export const apiGetDocument = async ({ user, path, division, category }: { user: string, path: string, division: string, category: 'all' | 'folder' }) => { + const response = await api.get(`mobile/document?user=${user}&path=${path}&division=${division}&category=${category}`); + return response.data; +}; + +export const apiGetDocumentInformasi = async ({ user, item, cat }: { user: string, item: string, cat: 'share' | 'lainnya' }) => { + const response = await api.get(`mobile/document/more?user=${user}&item=${item}&cat=${cat}`); + return response.data; +}; + +export const apiDocumentRename = async (data: { name: string, user: string, id: string, path: string, idDivision: string, extension: string }) => { + const response = await api.put(`/mobile/document`, data) + return response.data; +}; + +export const apiDocumentDelete = async (data: { user: string, data: any[] }) => { + const response = await api.delete(`/mobile/document`, { data }) + return response.data +}; + +export const apiCreateFolderDocument = async ({ data }: { data: { name: string, path: string, idDivision: string, user: string } }) => { + const response = await api.post(`/mobile/document`, data) + return response.data; +}; + +export const apiUploadFileDocument = async ({ data }: { data: FormData }) => { + const response = await api.post(`/mobile/document/upload`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiMoveDocument = async (data: { path: string, dataItem: any[], user: string }) => { + const response = await api.post(`/mobile/document/more`, data) + return response.data; +}; + +export const apiCopyDocument = async (data: { path: string, dataItem: any[], user: string, idDivision: string }) => { + const response = await api.put(`/mobile/document/more`, data) + return response.data; +}; + +export const apiShareDocument = async (data: { dataDivision: any[], dataItem: any[], user: string }) => { + const response = await api.delete(`/mobile/document/more`, { data }) + return response.data; +}; diff --git a/lib/api/group.api.ts b/lib/api/group.api.ts new file mode 100644 index 0000000..3d2057b --- /dev/null +++ b/lib/api/group.api.ts @@ -0,0 +1,46 @@ +import api from './client'; + +export const apiGetGroup = async ({ user, active, search }: { user: string, active: string, search: string }) => { + const response = await api.get(`mobile/group?user=${user}&active=${active}&search=${search}`); + return response.data; +}; + +export const apiCreateGroup = async (data: { user: string, name: string }) => { + const response = await api.post('mobile/group', data); + return response.data; +}; + +export const apiEditGroup = async (data: { user: string, name: string }, id: string) => { + const response = await api.put(`mobile/group/${id}`, data); + return response.data; +}; + +export const apiDeleteGroup = async (data: { user: string, isActive: boolean }, id: string) => { + const response = await api.delete(`mobile/group/${id}`, { data }); + return response.data; +}; + +export const apiGetDivisionGroup = async ({ user }: { user: string }) => { + const response = await api.get(`mobile/group/get-division?user=${user}`); + return response.data; +}; + +export const apiGetPosition = async ({ user, active, search, group }: { user: string, active: string, search: string, group?: string }) => { + const response = await api.get(`mobile/position?user=${user}&active=${active}&group=${group}&search=${search}`); + return response.data; +}; + +export const apiCreatePosition = async (data: { user: string, name: string, idGroup: string }) => { + const response = await api.post('mobile/position', data); + return response.data; +}; + +export const apiDeletePosition = async (data: { user: string, isActive: boolean }, id: string) => { + const response = await api.delete(`mobile/position/${id}`, { data }); + return response.data; +}; + +export const apiEditPosition = async (data: { user: string, name: string, idGroup: string }, id: string) => { + const response = await api.put(`mobile/position/${id}`, data) + return response.data +}; diff --git a/lib/api/home.api.ts b/lib/api/home.api.ts new file mode 100644 index 0000000..87b00f9 --- /dev/null +++ b/lib/api/home.api.ts @@ -0,0 +1,26 @@ +import api from './client'; + +export const apiGetDataHome = async ({ cat, user }: { cat: 'kegiatan' | 'division' | 'progress' | 'dokumen' | 'event' | 'discussion' | 'header' | 'check-late-project', user: string }) => { + const response = await api.get(`mobile/home?user=${user}&cat=${cat}`); + return response.data; +}; + +export const apiGetSearch = async ({ text, user }: { text: string, user: string }) => { + const response = await api.get(`mobile/home/search?search=${text}&user=${user}`); + return response.data; +}; + +export const apiGetNotification = async ({ user, page }: { user: string, page?: number }) => { + const response = await api.get(`mobile/home/notification?user=${user}&page=${page}`); + return response.data; +}; + +export const apiReadOneNotification = async (data: { user: string, id: string }) => { + const response = await api.put(`/mobile/home/notification`, data) + return response.data; +}; + +export const apiReadAllNotification = async (data: { user: string }) => { + const response = await api.post(`/mobile/home/notification`, data) + return response.data; +}; diff --git a/lib/api/index.ts b/lib/api/index.ts new file mode 100644 index 0000000..778a82a --- /dev/null +++ b/lib/api/index.ts @@ -0,0 +1,12 @@ +export * from './auth.api'; +export * from './user.api'; +export * from './group.api'; +export * from './banner.api'; +export * from './home.api'; +export * from './announcement.api'; +export * from './project.api'; +export * from './division.api'; +export * from './discussion.api'; +export * from './calendar.api'; +export * from './task.api'; +export * from './document.api'; diff --git a/lib/api/project.api.ts b/lib/api/project.api.ts new file mode 100644 index 0000000..5d26be2 --- /dev/null +++ b/lib/api/project.api.ts @@ -0,0 +1,144 @@ +import api from './client'; + +export const apiGetTahunProject = async ({ user }: { user: string }) => { + const response = await api.get(`mobile/project/tahun?user=${user}`); + return response.data; +}; + +export const apiGetProject = async ({ user, status, search, group, kategori, page, year }: { user: string, status: string, search: string, group?: string, kategori?: string, page?: number, year?: string }) => { + const response = await api.get(`mobile/project?user=${user}&status=${status}&group=${group}&search=${search}&cat=${kategori}&page=${page}&year=${year}`); + return response.data; +}; + +export const apiGetProjectOne = async ({ user, cat, id }: { user: string, cat: 'data' | 'progress' | 'task' | 'file' | 'member' | 'link', id: string }) => { + const response = await api.get(`mobile/project/${id}?user=${user}&cat=${cat}`); + return response.data; +}; + +export const apiCreateProject = async (data: FormData) => { + const response = await api.post(`/mobile/project`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiEditProject = async (data: { name: string, user: string }, id: string) => { + const response = await api.put(`/mobile/project/${id}`, data) + return response.data; +}; + +export const apiReportProject = async (data: { report: string, user: string }, id: string) => { + const response = await api.put(`/mobile/project/${id}/lainnya`, data) + return response.data; +}; + +export const apiCancelProject = async (data: { user: string, reason: string }, id: string) => { + const response = await api.delete(`mobile/project/${id}`, { data }) + return response.data +}; + +export const apiDeleteProject = async (data: { user: string }, id: string) => { + const response = await api.delete(`/mobile/project/${id}/lainnya`, { data }) + return response.data; +}; + +export const apiAddMemberProject = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => { + const response = await api.post(`/mobile/project/${id}/member`, data) + return response.data; +}; + +export const apiDeleteProjectMember = async (data: { user: string, idUser: string }, id: string) => { + const response = await api.delete(`mobile/project/${id}/member`, { data }) + return response.data +}; + +export const apiAddLinkProject = async (data: { user: string, link: string }, id: string) => { + const response = await api.post(`/mobile/project/${id}/link`, data) + return response.data; +}; + +export const apiDeleteLinkProject = async (data: { idLink: string, user: string }, id: string) => { + const response = await api.delete(`/mobile/project/${id}/link`, { data }) + return response.data; +}; + +export const apiAddFileProject = async ({ data, id }: { data: FormData, id: string }) => { + const response = await api.post(`/mobile/project/file/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiCheckFileProject = async ({ data, id }: { data: FormData, id: string }) => { + const response = await api.put(`/mobile/project/file/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiDeleteFileProject = async (data: { user: string }, id: string) => { + const response = await api.delete(`/mobile/project/file/${id}`, { data }) + return response.data; +}; + +export const apiCreateProjectTask = async ({ data, id }: { data: { name: string, dateStart: string, user: string, dateEnd: string, dataDetail: any[] }, id: string }) => { + const response = await api.post(`/mobile/project/${id}`, data) + return response.data; +}; + +export const apiUpdateStatusProjectTask = async (data: { user: string, status: number, idProject: string }, id: string) => { + const response = await api.put(`mobile/project/detail/${id}`, data) + return response.data +}; + +export const apiDeleteProjectTask = async (data: { user: string, idProject: string }, id: string) => { + const response = await api.delete(`mobile/project/detail/${id}`, { data }) + return response.data +}; + +export const apiGetProjectTask = async ({ user, id, cat }: { user: string, id: string, cat?: string }) => { + const response = await api.get(`mobile/project/detail/${id}?user=${user}${cat ? `&cat=${cat}` : ""}`); + return response.data; +}; + +export const apiEditProjectTask = async ({ data, id }: { data: { title: string, dateStart: string, user: string, dateEnd: string, dataDetail: any[] }, id: string }) => { + const response = await api.post(`/mobile/project/detail/${id}`, data) + return response.data; +}; + +export const apiGetProjectTaskFile = async ({ user, id }: { user: string, id: string }) => { + const response = await api.get(`/mobile/project/task/file/${id}`, { params: { user } }) + return response.data; +}; + +export const apiAddProjectTaskFile = async ({ data, id }: { data: FormData, id: string }) => { + const response = await api.post(`/mobile/project/task/file/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiLinkProjectTaskFile = async ({ user, idFile, id }: { user: string, idFile: string, id: string }) => { + const response = await api.patch(`/mobile/project/task/file/${id}`, { user, idFile }) + return response.data; +}; + +export const apiDeleteProjectTaskFile = async (data: { user: string }, id: string) => { + const response = await api.delete(`/mobile/project/task/file/${id}`, { data }) + return response.data; +}; + +export const apiGetProjectTaskApprovals = async ({ user, id }: { user: string, id: string }) => { + const response = await api.get(`/mobile/project/task/${id}/approval`, { params: { user } }) + return response.data; +}; + +export const apiSubmitProjectTask = async ({ user, id }: { user: string, id: string }) => { + const response = await api.post(`/mobile/project/task/${id}/approval`, { user }) + return response.data; +}; + +export const apiApproveRejectProjectTask = async ({ user, id, action, note }: { user: string, id: string, action: 'approve' | 'reject', note?: string }) => { + const response = await api.put(`/mobile/project/task/${id}/approval`, { user, action, note }) + return response.data; +}; diff --git a/lib/api/task.api.ts b/lib/api/task.api.ts new file mode 100644 index 0000000..1e8a505 --- /dev/null +++ b/lib/api/task.api.ts @@ -0,0 +1,144 @@ +import api from './client'; + +export const apiGetTask = async ({ user, status, search, division, page, year }: { user: string, status: string, search: string, division: string, page?: number, year?: string }) => { + const response = await api.get(`mobile/task?user=${user}&status=${status}&division=${division}&search=${search}&page=${page}&year=${year}`); + return response.data; +}; + +export const apiGetTahunTask = async ({ user, division }: { user: string, division: string }) => { + const response = await api.get(`mobile/task/tahun?user=${user}&division=${division}`); + return response.data; +}; + +export const apiGetTaskOne = async ({ user, cat, id }: { user: string, cat: 'data' | 'progress' | 'task' | 'file' | 'member' | 'link', id: string }) => { + const response = await api.get(`mobile/task/${id}?user=${user}&cat=${cat}`); + return response.data; +}; + +export const apiCreateTask = async (data: FormData) => { + const response = await api.post(`/mobile/task`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiEditTask = async (data: { title: string, user: string }, id: string) => { + const response = await api.put(`/mobile/task/${id}`, data) + return response.data; +}; + +export const apiReportTask = async (data: { report: string, user: string }, id: string) => { + const response = await api.put(`/mobile/task/${id}/lainnya`, data) + return response.data; +}; + +export const apiCancelTask = async (data: { user: string, reason: string }, id: string) => { + const response = await api.delete(`mobile/task/${id}`, { data }) + return response.data +}; + +export const apiDeleteTask = async (data: { user: string }, id: string) => { + const response = await api.delete(`/mobile/task/${id}/lainnya`, { data }) + return response.data; +}; + +export const apiAddMemberTask = async ({ data, id }: { data: { user: string, member: any[], idDivision: string }, id: string }) => { + const response = await api.post(`/mobile/task/${id}/member`, data) + return response.data; +}; + +export const apiDeleteTaskMember = async (data: { user: string, idUser: string }, id: string) => { + const response = await api.delete(`mobile/task/${id}/member`, { data }) + return response.data +}; + +export const apiAddLinkTask = async (data: { user: string, link: string, idDivision: string }, id: string) => { + const response = await api.post(`/mobile/task/${id}/link`, data) + return response.data; +}; + +export const apiDeleteLinkTask = async (data: { user: string, idLink: string }, id: string) => { + const response = await api.delete(`/mobile/task/${id}/link`, { data }) + return response.data; +}; + +export const apiAddFileTask = async ({ data, id }: { data: FormData, id: string }) => { + const response = await api.post(`/mobile/task/file/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiCheckFileTask = async ({ data, id }: { data: FormData, id: string }) => { + const response = await api.put(`/mobile/task/file/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiDeleteFileTask = async (data: { user: string }, id: string) => { + const response = await api.delete(`/mobile/task/file/${id}`, { data }) + return response.data; +}; + +export const apiUpdateStatusTaskDivision = async (data: { user: string, status: number, idProject: string }, id: string) => { + const response = await api.put(`mobile/task/detail/${id}`, data) + return response.data +}; + +export const apiGetTaskTugas = async ({ user, id, cat }: { user: string, id: string, cat?: string }) => { + const response = await api.get(`mobile/task/detail/${id}?user=${user}${cat ? `&cat=${cat}` : ""}`); + return response.data; +}; + +export const apiCreateTaskTugas = async ({ data, id }: { data: { title: string, dateStart: string, user: string, dateEnd: string, idDivision: string, dataDetail: any[] }, id: string }) => { + const response = await api.post(`/mobile/task/${id}`, data) + return response.data; +}; + +export const apiEditTaskTugas = async ({ data, id }: { data: { title: string, dateStart: string, user: string, dateEnd: string, dataDetail: any[] }, id: string }) => { + const response = await api.post(`/mobile/task/detail/${id}`, data) + return response.data; +}; + +export const apiDeleteTaskTugas = async (data: { user: string, idProject: string }, id: string) => { + const response = await api.delete(`mobile/task/detail/${id}`, { data }) + return response.data +}; + +export const apiGetTugasTaskFile = async ({ user, id }: { user: string, id: string }) => { + const response = await api.get(`/mobile/task/tugas/file/${id}`, { params: { user } }) + return response.data; +}; + +export const apiAddTugasTaskFile = async ({ data, id }: { data: FormData, id: string }) => { + const response = await api.post(`/mobile/task/tugas/file/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiLinkTugasTaskFile = async ({ user, idFile, id }: { user: string, idFile: string, id: string }) => { + const response = await api.patch(`/mobile/task/tugas/file/${id}`, { user, idFile }) + return response.data; +}; + +export const apiDeleteTugasTaskFile = async (data: { user: string }, id: string) => { + const response = await api.delete(`/mobile/task/tugas/file/${id}`, { data }) + return response.data; +}; + +export const apiGetTaskTugasApprovals = async ({ user, id }: { user: string, id: string }) => { + const response = await api.get(`/mobile/task/tugas/${id}/approval`, { params: { user } }) + return response.data; +}; + +export const apiSubmitTaskTugas = async ({ user, id }: { user: string, id: string }) => { + const response = await api.post(`/mobile/task/tugas/${id}/approval`, { user }) + return response.data; +}; + +export const apiApproveRejectTaskTugas = async ({ user, id, action, note }: { user: string, id: string, action: 'approve' | 'reject', note?: string }) => { + const response = await api.put(`/mobile/task/tugas/${id}/approval`, { user, action, note }) + return response.data; +}; diff --git a/lib/api/user.api.ts b/lib/api/user.api.ts new file mode 100644 index 0000000..a9f4588 --- /dev/null +++ b/lib/api/user.api.ts @@ -0,0 +1,42 @@ +import api from './client'; + +export const apiGetProfile = async ({ id }: { id: string }) => { + const response = await api.get(`mobile/user/${id}`); + return response.data; +}; + +export const apiEditProfile = async (data: FormData) => { + const response = await api.put(`/mobile/user/profile`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiGetUser = async ({ user, active, search, group, page }: { user: string, active: string, search: string, group?: string, page?: number }) => { + const response = await api.get(`mobile/user?user=${user}&active=${active}&group=${group}&search=${search}&page=${page}`); + return response.data; +}; + +export const apiCreateUser = async ({ data }: { data: FormData }) => { + const response = await api.post('/mobile/user', data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +}; + +export const apiDeleteUser = async (data: { user: string, isActive: boolean }, id: string) => { + const response = await api.delete(`mobile/user/${id}`, { data }) + return response.data +}; + +export const apiToggleApprover = async (data: { user: string, isApprover: boolean }, id: string) => { + const response = await api.patch(`mobile/user/${id}`, data) + return response.data +}; + +export const apiEditUser = async (data: FormData, id: string) => { + const response = await api.put(`/mobile/user/${id}`, data, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + return response.data; +};