├── .env.example ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── chakra.config.js ├── components ├── BaseComponents │ ├── ChromaButton │ │ └── index.jsx │ ├── ChromaDropdown │ │ └── index.jsx │ ├── ChromaToast │ │ └── index.jsx │ ├── DarkModeButton │ │ └── index.jsx │ ├── DateTimeFormat │ │ └── index.jsx │ ├── FloatingActionButton │ │ └── index.jsx │ ├── Footer │ │ └── index.jsx │ ├── InnerChildHTML │ │ └── index.jsx │ ├── NavigationSection │ │ └── index.jsx │ └── RupiahFormat │ │ └── index.jsx ├── DonatePage │ ├── DonateAlert │ │ └── index.jsx │ ├── DonateBadgeStatus │ │ └── index.jsx │ ├── DonateButton │ │ └── index.jsx │ ├── DonateDescription │ │ └── index.jsx │ ├── DonateFinish │ │ └── index.jsx │ ├── DonateForm │ │ └── index.jsx │ ├── DonateHistory │ │ └── index.jsx │ ├── DonateHistoryCardItem │ │ └── index.jsx │ ├── DonateHistoryPaginator │ │ └── index.jsx │ ├── DonateHistoryTable │ │ └── index.jsx │ ├── DonateModalDetail │ │ └── index.jsx │ ├── DonateModalUsername │ │ └── index.jsx │ └── DonateTab │ │ └── index.jsx ├── Homepage │ ├── BannerSection │ │ └── index.jsx │ ├── DonateSection │ │ └── index.jsx │ ├── GameModeSection │ │ └── index.jsx │ ├── HelpSection │ │ └── index.jsx │ └── ReportSection │ │ └── index.jsx └── WikiPage │ ├── DiscordLink │ └── index.jsx │ ├── RandomItemVoteTab │ └── index.jsx │ └── RulesTab │ └── index.jsx ├── context └── donate.js ├── lib └── gtag.jsx ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── _app.jsx ├── _document.jsx ├── api │ ├── donate-history.js │ ├── donate.js │ ├── payment.js │ ├── server.js │ └── users.js ├── donate.jsx ├── index.jsx └── wiki │ ├── donasi │ ├── index.mdx │ └── metode-pembayaran.mdx │ ├── fitur.mdx │ ├── index.mdx │ ├── more │ └── FAQ.mdx │ ├── rules │ ├── skyblock.mdx │ └── survival.mdx │ ├── tutorial │ ├── airdrop.mdx │ ├── marketplace.mdx │ ├── portable-gold-farm.mdx │ ├── redprotect.mdx │ └── trade.mdx │ └── vote.mdx ├── public ├── favicon.ico ├── img │ ├── airdrop-1.png │ ├── airdrop-2.png │ ├── bg.png │ ├── circle_base.png │ ├── discord-intro-channel.png │ ├── discord-intro-role-claim.png │ ├── discord-intro-role.png │ ├── discord-public.png │ ├── donasi-1.png │ ├── donasi-2.png │ ├── donasi-3.png │ ├── donasi-4.png │ ├── donasi-8.png │ ├── donasi-9.png │ ├── form-donasi-approved.png │ ├── goldfarm-1.png │ ├── goldfarm-booster.png │ ├── goldfarm-cara-1.png │ ├── goldfarm-cara-2.png │ ├── goldfarm-cara-3.png │ ├── goldfarm-menu.png │ ├── ic-arrow-up.svg │ ├── ic-book.svg │ ├── ic-circle-flat.svg │ ├── ic-fab.svg │ ├── ic-file.svg │ ├── ic-peoples.svg │ ├── ic-sound.svg │ ├── landing-page-banner-small.png │ ├── landing-page-banner.png │ ├── landing-page-bantuan.png │ ├── landing-page-donasi-medium.png │ ├── landing-page-donasi-small-darken.png │ ├── landing-page-donasi-small.png │ ├── landing-page-donasi.png │ ├── landing-page-laporan-small.png │ ├── landing-page-laporan.png │ ├── landing-page-minigame.png │ ├── landing-page-skyblock.png │ ├── landing-page-survival.png │ ├── logo.png │ ├── logo.svg │ ├── marketplace-main.png │ ├── marketplace-my-item-expired.png │ ├── marketplace-my-item-listed.png │ ├── marketplace-my-item-sold.png │ ├── payment_method_tutorial_1.png │ ├── payment_method_tutorial_2.png │ ├── payment_method_tutorial_3.png │ ├── payment_method_tutorial_4.png │ ├── payment_method_tutorial_5.png │ ├── payment_method_tutorial_trx_1.png │ ├── payment_method_tutorial_trx_2.png │ ├── redprotect-cara-1.png │ ├── redprotect-cara-2.png │ ├── redprotect-main.png │ ├── trade-cara-1.png │ ├── trade-cara-2.png │ └── trade-main.png └── vercel.svg ├── styles └── globals.css └── utils └── constant.js /.env.example: -------------------------------------------------------------------------------- 1 | BACKEND_IP='' 2 | BACKEND_PORT='' 3 | BASE_URL='' 4 | 5 | NEXT_PUBLIC_GOOGLE_ANALYTICS_ID='' 6 | 7 | NEXT_PUBLIC_RECAPTCHA_SITE_KEY='' 8 | RECAPTCHA_SECRET_KEY='' 9 | 10 | MINECRAFT_MP_SERVER_KEY='' 11 | 12 | NEXT_PUBLIC_HOTJAR_ID= 13 | NEXT_PUBLIC_HOTJAR_VERSION= 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: Aldiwildan77, Fakhri1999 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: Aldiwildan77 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | .env 33 | 34 | # vercel 35 | .vercel 36 | 37 | # mdx generated file 38 | /sidebar.json -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | https://discord.chroma-gaming.xyz. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guide 2 | 3 | Interested in contributing to this project? As an open source project, we'd really appreciate any 4 | help and contributions! 5 | 6 | ## Contribute code for this project 7 | 8 | Here's how to submit a Pull Request (PR): 9 | 10 | 1. [Fork this repository on GitHub][fork]. 11 | * If you have forked this repository, please follow the following guide. 12 | * Setup an [Upstream remote][configure-upstream] to this repository 13 | `https://github.com/ChromaMinecraft/chroma-minecraft-frontend.git` 14 | * [Sync your fork][sync-fork] with the upstream. 15 | 2. Clone your fork of the repository to your local computer. 16 | 3. Create a branch with descriptive name to work 17 | - feature: `git checkout -b feature/add-feature-x` push into `development` branch. 18 | - bugfix: `git checkout -b bugfix/missing-arguments` push into `development` branch. 19 | 4. Make changes, commit them, and push the branch to your repository fork. 20 | 5. Writing unit test would be appreciated. 21 | 6. [Submit a pull request][pull-req] to the master branch. 22 | 7. Address review comments if any. 23 | 24 | [fork]: https://help.github.com/articles/fork-a-repo 25 | [configure-upstream]: https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/configuring-a-remote-for-a-fork 26 | [sync-fork]: https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/syncing-a-fork 27 | [pull-req]: https://help.github.com/articles/using-pull-requests 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Chroma Minecraft 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Chroma Minecraft Website 2 | 3 | Chroma Minecraft adalah server dibawah naungan Komunitas Chroma. Chroma Minecraft mendukung berbagai platform (Java/Bedrock/Pocket Edition). 4 | -------------------------------------------------------------------------------- /chakra.config.js: -------------------------------------------------------------------------------- 1 | import { extendTheme } from "@chakra-ui/react"; 2 | const config = { 3 | styles: { 4 | global: { 5 | body: { 6 | fontFamily: "'Inter', sans-serif", 7 | }, 8 | }, 9 | }, 10 | }; 11 | const theme = extendTheme(config); 12 | export default theme; 13 | -------------------------------------------------------------------------------- /components/BaseComponents/ChromaButton/index.jsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@chakra-ui/react'; 2 | import React from 'react'; 3 | 4 | const typesList = { 5 | primaryFlat: 'primaryFlat', 6 | primary: 'primary', 7 | secondary: 'secondary', 8 | link: 'link', 9 | }; 10 | 11 | const ChromaButton = ({ types, children, ...rest }) => { 12 | const typesMap = { 13 | [typesList.primary]: () => , 14 | [typesList.secondary]: () => , 15 | [typesList.link]: () => , 16 | [typesList.primaryFlat]: () => , 17 | }; 18 | 19 | const PrimaryFlat = () => ( 20 | 41 | ); 42 | 43 | const Primary = () => { 44 | return ( 45 | 71 | ); 72 | }; 73 | 74 | const Secondary = () => { 75 | return ( 76 | 90 | ); 91 | }; 92 | 93 | const Link = () => { 94 | return ( 95 | 103 | ); 104 | }; 105 | 106 | return typesMap[types](); 107 | }; 108 | 109 | export { ChromaButton, typesList }; 110 | -------------------------------------------------------------------------------- /components/BaseComponents/ChromaDropdown/index.jsx: -------------------------------------------------------------------------------- 1 | import { Select } from '@chakra-ui/react'; 2 | import React from 'react'; 3 | 4 | const ChromaDropdown = ({ options, ...props }) => { 5 | return ( 6 | <> 7 | 22 | 23 | ); 24 | }; 25 | 26 | export default ChromaDropdown; 27 | -------------------------------------------------------------------------------- /components/BaseComponents/ChromaToast/index.jsx: -------------------------------------------------------------------------------- 1 | import { Box, Text } from '@chakra-ui/react'; 2 | import React from 'react'; 3 | 4 | const ChromaToast = ({ title, subtitle, ...rest }) => { 5 | return ( 6 | <> 7 | 17 | 18 | {title} 19 | 20 | 21 | {subtitle} 22 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | export default ChromaToast; 29 | -------------------------------------------------------------------------------- /components/BaseComponents/DarkModeButton/index.jsx: -------------------------------------------------------------------------------- 1 | import { Box, useColorMode } from '@chakra-ui/react'; 2 | import { FiMoon, FiSun } from 'react-icons/fi'; 3 | 4 | export default function DarkModeButton() { 5 | const { colorMode, toggleColorMode } = useColorMode(); 6 | return ( 7 | 22 | {colorMode === 'dark' ? : } 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /components/BaseComponents/DateTimeFormat/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import dayjs from 'dayjs'; 3 | import customParseFormat from 'dayjs/plugin/customParseFormat'; 4 | import { 5 | DATE_STANDARD_FORMAT, 6 | DATE_TIME_STANDARD_FORMAT, 7 | } from '../../../utils/constant'; 8 | 9 | dayjs.extend(customParseFormat); 10 | 11 | const DateTimeFormat = ({ date, currentFormat, toFormat, ...props }) => { 12 | if (!currentFormat) currentFormat = DATE_TIME_STANDARD_FORMAT; 13 | if (!toFormat) toFormat = DATE_STANDARD_FORMAT; 14 | 15 | return <>{dayjs(date, currentFormat).format(toFormat)}; 16 | }; 17 | 18 | export default DateTimeFormat; 19 | -------------------------------------------------------------------------------- /components/BaseComponents/FloatingActionButton/index.jsx: -------------------------------------------------------------------------------- 1 | import { Box, Image } from '@chakra-ui/react'; 2 | import React from 'react'; 3 | 4 | const FloatingActionButtonItem = ({ ...props }) => { 5 | return ( 6 | { 14 | e.preventDefault(); 15 | window.scrollTo({ 16 | top: 0, 17 | behavior: 'smooth', 18 | }); 19 | }} 20 | _hover={{ 21 | cursor: 'pointer', 22 | transform: 'scale(1.05)', 23 | transition: 'all .2s ease-in-out', 24 | }} 25 | _focus={{ 26 | outline: 'none', 27 | }} 28 | > 29 | 30 | 31 | ); 32 | }; 33 | 34 | const FloatingActionButton = ({ children, ...props }) => { 35 | return ( 36 | <> 37 | {children} 38 | 39 | 40 | ); 41 | }; 42 | 43 | export default FloatingActionButton; 44 | -------------------------------------------------------------------------------- /components/BaseComponents/Footer/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Flex, 4 | Container, 5 | Box, 6 | SimpleGrid, 7 | Image, 8 | Text, 9 | Stack, 10 | Link, 11 | Button, 12 | useToast, 13 | } from '@chakra-ui/react'; 14 | import { FaDiscord } from 'react-icons/fa'; 15 | import copy from 'copy-to-clipboard'; 16 | 17 | import { ChromaButton, typesList } from '../ChromaButton'; 18 | import ChromaToast from '../ChromaToast'; 19 | 20 | const Footer = () => { 21 | const toast = useToast(); 22 | return ( 23 | <> 24 | 25 | 26 | 27 | 31 | 36 | 37 | 38 | 45 | 46 | 52 | Chroma Minecraft 53 | 54 | 55 | 56 | 57 | Berbeda perangkat dengan temanmu, bukan masalah! Temukan 58 | banyak keseruan dengan plugin original kami, serta 59 | event-event menarik untukmu dan temanmu. Bersama misteri, 60 | harta karun, dan creeper tentunya. 61 | 62 | 63 | { 66 | e.preventDefault(); 67 | copy('mc.chroma-gaming.xyz'); 68 | toast({ 69 | duration: 1500, 70 | position: 'top-right', 71 | render: () => { 72 | return ( 73 | 77 | ); 78 | }, 79 | }); 80 | }} 81 | > 82 | Mainkan Sekarang 🡢 83 | 84 | 85 | 86 | 87 | Navigasi 88 | 89 | 90 | Mode Permainan 91 | 92 | 93 | Donasi 94 | 95 | 96 | Vote 97 | 98 | 99 | Bantuan 100 | 101 | 102 | Laporan 103 | 104 | 105 | 110 | 111 | 112 | Skuy lah mabar! 113 | 114 | 115 | Nyari temen main, mau tanya-tanya admin, jual barang-barang 116 | hasil mining, semuanya bisa. Skuy gasken join discord kita 117 | aja 118 | 119 | 120 | } 124 | href='https://discord.chroma-gaming.xyz' 125 | target='_blank' 126 | > 127 | Join Discord 128 | 129 | 130 | 131 | 132 | 133 | 134 | {/* Made with love */} 135 | 136 | 137 | 138 | 139 | Made with ❤️ by Chroma Developer Team 140 | 141 | 142 | 143 | 144 | 145 | ); 146 | }; 147 | 148 | export default Footer; 149 | -------------------------------------------------------------------------------- /components/BaseComponents/InnerChildHTML/index.jsx: -------------------------------------------------------------------------------- 1 | const InnerChildHTML = ({ text }) => { 2 | return
; 3 | }; 4 | 5 | export default InnerChildHTML; 6 | -------------------------------------------------------------------------------- /components/BaseComponents/NavigationSection/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Collapse, 4 | Container, 5 | Flex, 6 | HStack, 7 | Image, 8 | Link, 9 | Stack, 10 | Text, 11 | useDisclosure, 12 | } from '@chakra-ui/react'; 13 | import React, { useEffect, useState } from 'react'; 14 | import HamburgerMenu from 'react-hamburger-menu'; 15 | 16 | const Links = [ 17 | { 18 | label: 'Mode Permainan', 19 | link: '/#nav-gamemode', 20 | }, 21 | { 22 | label: 'Donasi', 23 | link: '/#nav-donate', 24 | }, 25 | { 26 | label: 'Vote', 27 | link: '/#nav-donate', 28 | }, 29 | { 30 | label: 'Bantuan', 31 | link: '/#nav-help', 32 | }, 33 | { 34 | label: 'Laporan', 35 | link: '/#nav-report', 36 | }, 37 | ]; 38 | 39 | const NavLink = ({ children, ...props }) => ( 40 | 51 | {children} 52 | 53 | ); 54 | 55 | const NavigationSection = () => { 56 | const { isOpen, onToggle } = useDisclosure(); 57 | const [isTransparent, setIsTransparent] = useState(true); 58 | 59 | const changeBackground = () => { 60 | if (window.scrollY >= 500) { 61 | setIsTransparent(false); 62 | } else { 63 | setIsTransparent(true); 64 | } 65 | }; 66 | 67 | useEffect(() => { 68 | changeBackground(); 69 | window.addEventListener('scroll', changeBackground); 70 | }); 71 | 72 | return ( 73 | <> 74 | 92 | 93 | 94 | 95 | 96 | 103 | 104 | 105 | Chroma Minecraft 106 | 107 | 108 | 109 | 110 | 116 | {Links.map((data, idx) => ( 117 | 118 | {data.label} 119 | 120 | ))} 121 | 122 | 123 | 124 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | {Links.map((data, idx) => ( 142 | 143 | {data.label} 144 | 145 | ))} 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | ); 154 | }; 155 | 156 | export default NavigationSection; 157 | -------------------------------------------------------------------------------- /components/BaseComponents/RupiahFormat/index.jsx: -------------------------------------------------------------------------------- 1 | import { Text } from '@chakra-ui/react'; 2 | import NumberFormat from 'react-number-format'; 3 | 4 | export default function RupiahFormat({ value, fontWeight, fontSize, ...rest }) { 5 | const fSize = !fontSize ? ['sm', 'md'] : fontSize; 6 | 7 | return ( 8 | ( 18 | 19 | {value} 20 | 21 | )} 22 | /> 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /components/DonatePage/DonateAlert/index.jsx: -------------------------------------------------------------------------------- 1 | import { Alert, AlertIcon, AlertDescription } from '@chakra-ui/react'; 2 | 3 | export default function DonateAlert({ status, children, ...props }) { 4 | return ( 5 | 14 | 15 | {children} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /components/DonatePage/DonateBadgeStatus/index.jsx: -------------------------------------------------------------------------------- 1 | import { Badge } from '@chakra-ui/react'; 2 | 3 | const DonateBadgeStatus = ({ status }) => { 4 | const colorSchemeStatus = { 5 | PAID: 'green', 6 | FAILED: 'red', 7 | UNPAID: 'gray', 8 | REFUND: 'yellow', 9 | }; 10 | 11 | const color = colorSchemeStatus[status] 12 | ? colorSchemeStatus[status] 13 | : 'blackAlpha'; 14 | 15 | return ( 16 | 22 | {status} 23 | 24 | ); 25 | }; 26 | 27 | export default DonateBadgeStatus; 28 | -------------------------------------------------------------------------------- /components/DonatePage/DonateButton/index.jsx: -------------------------------------------------------------------------------- 1 | import copy from 'copy-to-clipboard'; 2 | import React from 'react'; 3 | import { ChromaButton, typesList } from '../../BaseComponents/ChromaButton'; 4 | import ChromaToast from '../../BaseComponents/ChromaToast'; 5 | 6 | const DonateAction = { 7 | PAID: ({ redeem_code, toast }) => ( 8 | 9 | ), 10 | UNPAID: ({ checkout_url }) => , 11 | }; 12 | 13 | const DonatePayNow = ({ checkout_url }) => ( 14 | 15 | Bayar Sekarang 16 | 17 | ); 18 | 19 | const DonateCopyCC = ({ redeem_code, toast }) => ( 20 | { 23 | copy(redeem_code); 24 | toast({ 25 | duration: 1500, 26 | position: 'top-right', 27 | render: () => { 28 | return ( 29 | 33 | ); 34 | }, 35 | }); 36 | }} 37 | > 38 | Salin Kode CC 39 | 40 | ); 41 | 42 | const DonateCardActionButton = (props) => { 43 | if (!DonateAction[props.donation_status]) return <>; 44 | return DonateAction[props.donation_status](props); 45 | }; 46 | 47 | export { DonateCopyCC, DonatePayNow, DonateCardActionButton }; 48 | -------------------------------------------------------------------------------- /components/DonatePage/DonateDescription/index.jsx: -------------------------------------------------------------------------------- 1 | import { Text } from '@chakra-ui/react'; 2 | import React, { useContext } from 'react'; 3 | import { DonateContext } from '../../../context/donate'; 4 | 5 | const DonateDescription = ({ ...props }) => { 6 | const { username, modalUsernameShown } = useContext(DonateContext); 7 | 8 | return ( 9 | <> 10 | 16 | Donasi 17 | 18 | 25 | Hello, {!modalUsernameShown && username} 26 | 27 | 28 | Makasih banyak nih udah mau donasi, dengan bantuanmu kita bisa sampai 29 | sejauh ini. Kalau sendirian server kita ini nggak akan sampai sebagus 30 | ini. Dukung kami terus ya, masih banyak hal yang pingin kita tunjukkin 31 | ke kamu kok 😁 32 | 33 | 34 | ); 35 | }; 36 | 37 | export default DonateDescription; 38 | -------------------------------------------------------------------------------- /components/DonatePage/DonateFinish/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Modal, 3 | ModalOverlay, 4 | ModalContent, 5 | ModalHeader, 6 | ModalBody, 7 | Text, 8 | } from '@chakra-ui/react'; 9 | import { ChromaButton, typesList } from '../../BaseComponents/ChromaButton'; 10 | 11 | export default function DonateFinish({ isOpen, onClose, ...props }) { 12 | return ( 13 | 14 | 15 | 16 | Donasi 17 | 18 | 19 | Terimakasih telah melakukan pembayaran. Silahkan tunggu hingga 20 | sistem memverifikasi pembayaranmu dan kode CC mu akan dikirim 21 | otomatis oleh sistem pada email mu. 22 | 23 | 30 | Tutup 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /components/DonatePage/DonateForm/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | FormControl, 3 | FormLabel, 4 | FormHelperText, 5 | Input, 6 | NumberInput, 7 | NumberInputField, 8 | NumberInputStepper, 9 | NumberIncrementStepper, 10 | NumberDecrementStepper, 11 | Select, 12 | Flex, 13 | Spacer, 14 | Text, 15 | Box, 16 | useToast, 17 | } from '@chakra-ui/react'; 18 | import Axios from 'axios'; 19 | import { useEffect, useState, useRef, useContext } from 'react'; 20 | import ReCAPTCHA from 'react-google-recaptcha'; 21 | 22 | import DonateAlert from '../DonateAlert'; 23 | import RupiahFormat from '../../BaseComponents/RupiahFormat'; 24 | import ChromaToast from '../../BaseComponents/ChromaToast'; 25 | 26 | import * as gtag from '../../../lib/gtag'; 27 | import { ChromaButton, typesList } from '../../BaseComponents/ChromaButton'; 28 | import { DonateContext } from '../../../context/donate'; 29 | import { EMAIL_REGEX_PATTERN } from '../../../utils/constant'; 30 | 31 | export default function DonateForm() { 32 | const [isAlertShown, setIsAlertShown] = useState(false); 33 | const [isSubmitButtonLoading, setIsSubmitButtonLoading] = useState(false); 34 | const [alertMessage, setAlertMessage] = useState(''); 35 | const [alertStatus, setAlertStatus] = useState(''); 36 | const [paymentList, setPaymentList] = useState([]); 37 | const [selectedPayment, setSelectedPayment] = useState({}); 38 | const [email, setEmail] = useState(''); 39 | const [donationAmount, setDonationAmount] = useState(10); 40 | const [donationPrice, setDonationPrice] = useState(1000); 41 | const [isSubmitButtonAllowed, setIsSubmitButtonAllowed] = useState(true); 42 | const [subTotal, setSubTotal] = useState(0); 43 | const [totalFee, setTotalFee] = useState(0); 44 | const [totalPrice, setTotalPrice] = useState(1000); 45 | const recaptchaRef = useRef(null); 46 | const toast = useToast(); 47 | 48 | const { username } = useContext(DonateContext); 49 | 50 | const offlinePayment = ['Indomaret']; 51 | const maxDonationAmount = 2000; 52 | const minDonationAmount = 10; 53 | 54 | const onEmailChangeValidator = (email) => { 55 | const pattern = new RegExp(EMAIL_REGEX_PATTERN); 56 | return pattern.test(email); 57 | }; 58 | 59 | const onFormDonationSubmit = (e) => { 60 | e && e.preventDefault(); 61 | recaptchaRef.current.execute(); 62 | }; 63 | 64 | const payDonation = async (captchaCode) => { 65 | setIsAlertShown(false); 66 | setIsSubmitButtonLoading(true); 67 | 68 | gtag.event({ 69 | action: 'Donate Buy', 70 | category: 'Donate', 71 | label: 'Donate Label', 72 | }); 73 | 74 | try { 75 | const result = await Axios({ 76 | url: '/api/donate', 77 | method: 'POST', 78 | data: JSON.stringify({ 79 | quantity: donationAmount, 80 | username, 81 | email, 82 | payment_method: selectedPayment.method, 83 | captchaCode, 84 | }), 85 | headers: { 86 | 'Content-Type': 'application/json', 87 | }, 88 | }); 89 | 90 | setAlertStatus('success'); 91 | setAlertMessage('Kamu akan segera diarahkan ke halaman pembayaran'); 92 | setTimeout(() => { 93 | window.location.href = result.data.data.checkout_url; 94 | }, 2000); 95 | } catch (error) { 96 | setAlertMessage(error.response.data.message); 97 | setAlertStatus('error'); 98 | setIsSubmitButtonLoading(false); 99 | } 100 | 101 | recaptchaRef.current.reset(); 102 | setIsAlertShown(true); 103 | }; 104 | 105 | const onReCAPTCHAChange = async (captchaCode) => { 106 | if (!captchaCode) return; 107 | payDonation(captchaCode); 108 | }; 109 | 110 | const handleEmailChange = (e) => { 111 | const email = e.target.value; 112 | setEmail(email); 113 | 114 | if (email.length > 0 && onEmailChangeValidator(email) && username) { 115 | setIsSubmitButtonAllowed(false); 116 | } else { 117 | setIsSubmitButtonAllowed(true); 118 | } 119 | }; 120 | 121 | const handleAmountChange = (e) => { 122 | setDonationAmount(parseFloat(e)); 123 | }; 124 | 125 | const handlePaymentChange = (e) => { 126 | const feeFlat = parseFloat( 127 | e.target[event.target.selectedIndex].getAttribute('data-fee-flat') 128 | ); 129 | const feePercent = parseFloat( 130 | e.target[event.target.selectedIndex].getAttribute('data-fee-percent') 131 | ); 132 | setSelectedPayment({ 133 | feeFlat: feeFlat, 134 | feePercent: feePercent, 135 | method: e.target.value, 136 | name: e.target[event.target.selectedIndex].text, 137 | }); 138 | }; 139 | 140 | useEffect(() => { 141 | const getPaymentList = async () => { 142 | setIsSubmitButtonLoading(true); 143 | try { 144 | const result = await Axios({ 145 | url: '/api/payment', 146 | method: 'GET', 147 | }); 148 | setPaymentList(result.data.data); 149 | const { 150 | code, 151 | fee_customer: { flat, percent }, 152 | } = result.data.data[0]; 153 | 154 | setSelectedPayment({ 155 | feeFlat: flat, 156 | feePercent: percent, 157 | method: code, 158 | }); 159 | } catch (error) { 160 | toast({ 161 | duration: null, 162 | position: 'top-right', 163 | render: () => { 164 | return ( 165 | 169 | ); 170 | }, 171 | }); 172 | } 173 | 174 | setIsSubmitButtonLoading(false); 175 | }; 176 | 177 | getPaymentList(); 178 | }, []); 179 | 180 | useEffect(() => { 181 | const calculateTotalPrice = () => { 182 | const feeFlat = parseFloat(selectedPayment.feeFlat); 183 | const feePercent = parseFloat(selectedPayment.feePercent); 184 | const subTotal = donationAmount * donationPrice; 185 | const totalFee = (subTotal * feePercent) / 100 + feeFlat; 186 | const totalPrice = subTotal + totalFee; 187 | setSubTotal(subTotal); 188 | setTotalFee(totalFee); 189 | setTotalPrice(totalPrice); 190 | }; 191 | 192 | calculateTotalPrice(); 193 | }, [selectedPayment, donationAmount]); 194 | 195 | return ( 196 | <> 197 | {isAlertShown && ( 198 | {alertMessage} 199 | )} 200 |
onFormDonationSubmit(e)}> 201 | 202 | 203 | Alamat Email 204 | 205 | 206 | 216 | 217 | 218 | 219 | 220 | Jumlah Chroma Cash 221 | 222 | 230 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | * Jumlah pembelian minimum CC adalah 10 241 | 242 | 243 | 244 | 245 | Pilih Metode Pembayaran 246 | 247 | 265 | 266 | * Metode pembayaran telah diurutkan berdasarkan biaya admin terendah 267 | 268 | 269 | {offlinePayment.includes(selectedPayment.name) && ( 270 | 271 | 272 | 273 | * Terdapat biaya administrasi tambahan untuk pembayaran ini. 274 | 275 | 276 | 277 | )} 278 | 286 | 287 | Sub Total 288 | 289 | 290 | 291 | 292 | Fee 293 | 294 | 295 | 296 | 297 | 298 | 308 | Total 309 | 310 | 311 | 312 | 318 | 319 | 327 | Bayar 328 | 329 | 337 | Butuh Bantuan? 338 | 339 | 340 | 341 | 342 | ); 343 | } 344 | -------------------------------------------------------------------------------- /components/DonatePage/DonateHistory/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | FormControl, 3 | FormLabel, 4 | Input, 5 | Button, 6 | Flex, 7 | Box, 8 | } from '@chakra-ui/react'; 9 | import { FaSearch } from 'react-icons/fa'; 10 | import { useState, useEffect, useRef } from 'react'; 11 | import Axios from 'axios'; 12 | import { useRouter } from 'next/router'; 13 | 14 | import DonateHistoryTable from '../DonateHistoryTable'; 15 | import DonateAlert from '../DonateAlert'; 16 | 17 | import * as gtag from '../../../lib/gtag'; 18 | 19 | export default function DonateHistory(props) { 20 | const [currentPage, setCurrentPage] = useState(1); 21 | const [isAlertShown, setIsAlertShown] = useState(false); 22 | const [alertMessage, setAlertMessage] = useState(''); 23 | const [alertStatus, setAlertStatus] = useState(''); 24 | const [username, setUsername] = useState(''); 25 | const [donationHistoryData, setDonationHistoryData] = useState(''); 26 | const [donationHistoryMeta, setDonationHistoryMeta] = useState({}); 27 | const [isButtonLoading, setIsButtonLoading] = useState(false); 28 | const [sortBy, setSortBy] = useState('desc'); 29 | const [orderBy, setOrderBy] = useState(''); 30 | 31 | const router = useRouter(); 32 | 33 | const handleUsernameChange = (e) => { 34 | setUsername(e.target.value); 35 | }; 36 | 37 | const handleUsernameKeyPress = (e) => { 38 | if (e.key === 'Enter') getDonationHistory(); 39 | }; 40 | 41 | const getDonationHistory = async (usernameParam = '') => { 42 | setIsAlertShown(false); 43 | setIsButtonLoading(true); 44 | setDonationHistoryData([]); 45 | if (usernameParam) { 46 | setUsername(usernameParam); 47 | } 48 | gtag.event({ 49 | action: 'Donate Check History', 50 | category: 'Donate', 51 | label: 'Donate Label', 52 | }); 53 | try { 54 | const result = await Axios({ 55 | url: `/api/donate-history?username=${ 56 | usernameParam === '' ? username : usernameParam 57 | }&page=${currentPage}&sort_by=${sortBy}&order_by=${orderBy}`, 58 | method: 'GET', 59 | }); 60 | setDonationHistoryData(result.data.data); 61 | setDonationHistoryMeta(result.data.meta); 62 | if (!result.data.data.length) { 63 | setAlertStatus('warning'); 64 | setAlertMessage('Data kosong'); 65 | setIsAlertShown(true); 66 | } 67 | } catch (error) { 68 | setDonationHistoryData([]); 69 | setAlertStatus('error'); 70 | setAlertMessage(error.response.data.message); 71 | setIsAlertShown(true); 72 | } 73 | setIsButtonLoading(false); 74 | }; 75 | 76 | const initialRender = useRef(true); 77 | 78 | useEffect(() => { 79 | if (initialRender.current) { 80 | initialRender.current = false; 81 | } else { 82 | getDonationHistory(); 83 | } 84 | }, [currentPage, sortBy, orderBy]); 85 | 86 | useEffect(() => { 87 | if (router.query.username != null) { 88 | getDonationHistory(router.query.username); 89 | } 90 | }, [router.query.username]); 91 | 92 | return ( 93 | 94 | {isAlertShown && ( 95 | {alertMessage} 96 | )} 97 | 98 | 99 | Username Minecraft 100 | 101 | 102 | handleUsernameChange(e)} 110 | onKeyPress={(e) => handleUsernameKeyPress(e)} 111 | fontSize={['sm', 'md']} 112 | /> 113 | 121 | 122 | 123 | {donationHistoryData && ( 124 | 135 | )} 136 | 137 | ); 138 | } 139 | -------------------------------------------------------------------------------- /components/DonatePage/DonateHistoryCardItem/index.jsx: -------------------------------------------------------------------------------- 1 | import { Box, Flex, Image, Text, useToast } from '@chakra-ui/react'; 2 | import { useContext } from 'react'; 3 | 4 | import { ChromaButton, typesList } from '../../BaseComponents/ChromaButton'; 5 | import RupiahFormat from '../../BaseComponents/RupiahFormat'; 6 | import { 7 | DATE_STANDARD_FORMAT, 8 | DATE_TIME_STANDARD_FORMAT, 9 | } from '../../../utils/constant'; 10 | import DateTimeFormat from '../../BaseComponents/DateTimeFormat'; 11 | import { DonateContext } from '../../../context/donate'; 12 | import DonateBadgeStatus from '../DonateBadgeStatus'; 13 | import { DonateCardActionButton } from '../DonateButton'; 14 | 15 | const DonateHistoryCardItem = ({ ...props }) => { 16 | const { amount, total, created_at, order_id, donation_status } = props; 17 | const { setDonateDetail } = useContext(DonateContext); 18 | 19 | const toast = useToast(); 20 | props.toast = toast; 21 | 22 | const DonateDateText = ({ date }) => ( 23 | 24 | 29 | 30 | ); 31 | 32 | return ( 33 | <> 34 | 41 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {order_id} 55 | 56 | 57 | 62 | 63 | 64 | Jumlah Pembelian 65 | 66 | 67 | {amount} CC 68 | 69 | 70 | 71 | 72 | Total Pembayaran 73 | 74 | 75 | 76 | 77 | 82 | 83 | setDonateDetail(props)} 86 | > 87 | Lihat Detail Transaksi 88 | 89 | 90 | 91 | 92 | ); 93 | }; 94 | 95 | export default DonateHistoryCardItem; 96 | -------------------------------------------------------------------------------- /components/DonatePage/DonateHistoryPaginator/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Paginator, 3 | Previous, 4 | Next, 5 | PageGroup, 6 | Container, 7 | } from 'chakra-paginator'; 8 | import { useState } from 'react'; 9 | 10 | export default function DonateHistoryPaginator(props) { 11 | const [currentPage, setCurrentPage] = useState(1); 12 | 13 | const totalPage = props.totalPage || 1; 14 | const outerLimit = 1; 15 | const innerLimit = 2; 16 | 17 | const baseStyles = { 18 | w: 7, 19 | fontSize: 'sm', 20 | color: 'black', 21 | }; 22 | 23 | const normalStyles = { 24 | ...baseStyles, 25 | bg: '#24242980', 26 | color: 'white', 27 | }; 28 | 29 | const activeStyles = { 30 | ...baseStyles, 31 | bg: '#F0375B', 32 | color: 'white', 33 | }; 34 | 35 | const separatorStyles = { 36 | w: 7, 37 | bg: '#24242980', 38 | color: 'white', 39 | }; 40 | 41 | const handlePageChange = (nextPage) => { 42 | setCurrentPage(nextPage); 43 | props.setCurrentPage(nextPage); 44 | }; 45 | 46 | return ( 47 | <> 48 | 58 | 59 | Previous 60 | 61 | Next 62 | 63 | 64 | 65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /components/DonatePage/DonateHistoryTable/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Table, 3 | Thead, 4 | Tbody, 5 | Tfoot, 6 | Tr, 7 | Th, 8 | Td, 9 | Badge, 10 | useColorMode, 11 | Flex, 12 | chakra, 13 | HStack, 14 | Text, 15 | } from '@chakra-ui/react'; 16 | import { FaAngleRight, FaSort, FaSortDown, FaSortUp } from 'react-icons/fa'; 17 | import { useTable, useSortBy } from 'react-table'; 18 | import { useState } from 'react'; 19 | import DonateHistoryPaginator from '../DonateHistoryPaginator'; 20 | 21 | export default function DonateHistoryTable(props) { 22 | const numberPlus = (props.currentPage - 1) * 10; 23 | const { colorMode, toggleColorMode } = useColorMode(); 24 | const [isOrderByTime, setIsOrderByTime] = useState(true); 25 | const [isOrderByStatus, setIsOrderByStatus] = useState(false); 26 | 27 | const handleTimeHeaderClick = () => { 28 | setIsOrderByTime(true); 29 | setIsOrderByStatus(false); 30 | props.setOrderBy('created_at'); 31 | if (props.sortBy === 'asc') { 32 | props.setSortBy('desc'); 33 | } else { 34 | props.setSortBy('asc'); 35 | } 36 | }; 37 | 38 | const handleStatusHeaderClick = () => { 39 | setIsOrderByTime(false); 40 | setIsOrderByStatus(true); 41 | props.setOrderBy('status'); 42 | if (props.sortBy === 'asc') { 43 | props.setSortBy('desc'); 44 | } else { 45 | props.setSortBy('asc'); 46 | } 47 | }; 48 | 49 | const checkStatusRender = (status) => { 50 | let color; 51 | switch (status) { 52 | case 'PAID': 53 | color = 'green'; 54 | break; 55 | case 'FAILED': 56 | color = 'red'; 57 | break; 58 | case 'UNPAID': 59 | color = 'gray'; 60 | break; 61 | case 'REFUND': 62 | color = 'yellow'; 63 | break; 64 | default: 65 | color = 'blackAlpha'; 66 | break; 67 | } 68 | return ( 69 | 70 | {status} 71 | 72 | ); 73 | }; 74 | 75 | const handleButtonClick = (data) => { 76 | props.setIsDetail(true); 77 | props.setDetail(data); 78 | }; 79 | 80 | return ( 81 | <> 82 | 83 | 84 | 85 | 86 | 103 | 106 | 123 | 124 | 125 | 126 | 127 | {props.data.map((data, i) => ( 128 | handleButtonClick(data)} 135 | key={`donate-history-${i}`} 136 | fontWeight='light' 137 | > 138 | 139 | 140 | 141 | 142 | 145 | 146 | ))} 147 | 148 |
# handleTimeHeaderClick()} 88 | _hover={{ 89 | cursor: 'pointer', 90 | }} 91 | > 92 | 93 | Waktu{' '} 94 | {!isOrderByTime ? ( 95 | 96 | ) : props.sortBy === 'asc' ? ( 97 | 98 | ) : ( 99 | 100 | )} 101 | 102 | 104 | Jumlah 105 | handleStatusHeaderClick()} 108 | _hover={{ 109 | cursor: 'pointer', 110 | }} 111 | > 112 | 113 | Status{' '} 114 | {!isOrderByStatus ? ( 115 | 116 | ) : props.sortBy === 'asc' ? ( 117 | 118 | ) : ( 119 | 120 | )} 121 | 122 |
{i + 1 + numberPlus}{data.created_at}{data.amount}{checkStatusRender(data.donation_status)} 143 | 144 |
149 | 154 | 155 | ); 156 | } 157 | -------------------------------------------------------------------------------- /components/DonatePage/DonateModalDetail/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Flex, 3 | Text, 4 | Modal, 5 | ModalOverlay, 6 | ModalContent, 7 | ModalHeader, 8 | ModalCloseButton, 9 | ModalBody, 10 | Box, 11 | } from '@chakra-ui/react'; 12 | import { useContext } from 'react'; 13 | import DonateBadgeStatus from '../DonateBadgeStatus'; 14 | import RupiahFormat from '../../BaseComponents/RupiahFormat'; 15 | import { DonateContext } from '../../../context/donate'; 16 | import DateTimeFormat from '../../BaseComponents/DateTimeFormat'; 17 | import { DonateCardActionButton } from '../DonateButton'; 18 | import { DATE_TIME_FULL_FORMAT } from '../../../utils/constant'; 19 | 20 | const isObjectEmpty = (obj) => 21 | obj && 22 | Object.keys(obj).length === 0 && 23 | Object.getPrototypeOf(obj) === Object.prototype; 24 | 25 | const TextRowTitle = ({ children }) => { 26 | return ( 27 | 28 | {children} 29 | 30 | ); 31 | }; 32 | 33 | const TextRow = ({ left, right }) => { 34 | return ( 35 | 36 | 37 | {left} 38 | 39 | 44 | {right} 45 | 46 | 47 | ); 48 | }; 49 | 50 | export default function DonateModalDetail({ ...props }) { 51 | const { donateDetail, setDonateDetail } = useContext(DonateContext); 52 | 53 | const handleModalClose = () => setDonateDetail({}); 54 | 55 | const saleInfo = [ 56 | { 57 | left: Status Transaksi, 58 | right: , 59 | }, 60 | { 61 | left: Username, 62 | right: {donateDetail.username}, 63 | }, 64 | { 65 | left: Nomor Transaksi, 66 | right: {donateDetail.order_id}, 67 | }, 68 | { 69 | left: Waktu Pembelian, 70 | right: ( 71 | 75 | ), 76 | }, 77 | { 78 | left: Waktu Pembayaran Kadaluarsa, 79 | right: ( 80 | 84 | ), 85 | }, 86 | ]; 87 | 88 | const paymentInfo = [ 89 | { 90 | left: Jumlah Chroma Cash, 91 | right: {donateDetail.amount} CC, 92 | }, 93 | { 94 | left: Metode Pembayaran, 95 | right: {donateDetail.payment_code}, 96 | }, 97 | { 98 | left: Sub Total, 99 | right: ( 100 | 101 | ), 102 | }, 103 | { 104 | left: Biaya Admin, 105 | right: , 106 | }, 107 | { 108 | left: Total, 109 | right: , 110 | }, 111 | ]; 112 | 113 | return ( 114 | <> 115 | 122 | 123 | 124 | 125 | Detail Transaksi 126 | 127 | 128 | 129 | 130 | Informasi Pembelian 131 | {saleInfo.map((item, index) => ( 132 | 133 | ))} 134 | Informasi Pembayaran 135 | {paymentInfo.map((item, index) => ( 136 | 137 | ))} 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | ); 147 | } 148 | -------------------------------------------------------------------------------- /components/DonatePage/DonateModalUsername/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Divider, 3 | Flex, 4 | FormControl, 5 | FormLabel, 6 | Input, 7 | Modal, 8 | ModalBody, 9 | ModalContent, 10 | ModalFooter, 11 | ModalOverlay, 12 | } from '@chakra-ui/react'; 13 | import React, { useContext, useState } from 'react'; 14 | import { ChromaButton, typesList } from '../../BaseComponents/ChromaButton'; 15 | import DonateAlert from '../DonateAlert'; 16 | import InnerChildHTML from '../../BaseComponents/InnerChildHTML'; 17 | 18 | import * as gtag from '../../../lib/gtag'; 19 | import Axios from 'axios'; 20 | import { DonateContext } from '../../../context/donate'; 21 | 22 | const stateMessages = { 23 | info: { 24 | color: 'blue.500', 25 | message: 26 | 'Cek akun yang kamu gunakan di chroma minecraft, sebelum berdonasi atau melakukan pengecekan transaksi', 27 | }, 28 | success: { 29 | color: 'green.500', 30 | message: 'Username ditemukan', 31 | }, 32 | warning: { 33 | color: 'yellow.500', 34 | message: 'Username tidak ditemukan', 35 | }, 36 | error: { 37 | color: 'red.500', 38 | message: 'Terjadi kesalahan', 39 | }, 40 | }; 41 | 42 | const stateTypes = { 43 | info: 'info', 44 | success: 'success', 45 | warning: 'warning', 46 | error: 'error', 47 | }; 48 | 49 | const DonateModalUsername = ({ parentTake, ...props }) => { 50 | const [alertMessage, setAlertMessage] = useState(stateMessages.info.message); 51 | const [alertType, setAlertType] = useState(stateTypes.info); 52 | const [loading, setLoading] = useState(false); 53 | const { username, setUsername, modalUsernameShown, setModalUsernameShown } = 54 | useContext(DonateContext); 55 | 56 | const handleOnChangeUsername = (e) => { 57 | setUsername(e.target.value); 58 | }; 59 | 60 | const handleOnClickCheckUsername = (e = null) => { 61 | if (e) e.preventDefault(); 62 | checkUsername(username); 63 | }; 64 | 65 | const checkUsername = async (username) => { 66 | gtag.event({ 67 | action: 'Donate Check Username', 68 | category: 'Donate', 69 | label: 'Donate Label', 70 | }); 71 | 72 | if (!username) { 73 | setAlertType(stateTypes.warning); 74 | setAlertMessage('Username tidak boleh kosong.'); 75 | return; 76 | } 77 | 78 | setLoading(true); 79 | 80 | try { 81 | const result = await Axios({ 82 | url: '/api/users', 83 | method: 'GET', 84 | params: { 85 | username: username, 86 | }, 87 | headers: { 88 | 'Content-Type': 'application/json', 89 | }, 90 | }); 91 | 92 | if (result.status == 203) { 93 | setAlertType(stateTypes.warning); 94 | setAlertMessage( 95 | ${username} tidak ditemukan`} 97 | /> 98 | ); 99 | } else { 100 | setAlertType(stateTypes.warning); 101 | setAlertMessage(result.data.message); 102 | setModalUsernameShown(false); 103 | setUsername(username); 104 | } 105 | } catch (error) { 106 | setAlertType(stateTypes.error); 107 | setAlertMessage(error.response.data.message); 108 | } 109 | setLoading(false); 110 | }; 111 | 112 | return ( 113 | <> 114 | 120 | 121 | 122 | 123 | {alertMessage} 124 | 125 | 130 |
131 | 132 | 133 | 138 | Username Minecraftmu 139 | 140 | 147 | 148 | 149 | 150 | 156 | Cek Username 157 | 158 | 159 |
160 |
161 |
162 | 163 | ); 164 | }; 165 | 166 | export default DonateModalUsername; 167 | -------------------------------------------------------------------------------- /components/DonatePage/DonateTab/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Tabs, 3 | TabList, 4 | TabPanels, 5 | Tab, 6 | TabPanel, 7 | useToast, 8 | } from '@chakra-ui/react'; 9 | import React, { useContext, useEffect, useState } from 'react'; 10 | 11 | import DonateForm from '../DonateForm'; 12 | import DonateHistoryCardItem from '../DonateHistoryCardItem'; 13 | 14 | import 'react-perfect-scrollbar/dist/css/styles.css'; 15 | import { DonateContext } from '../../../context/donate'; 16 | import InfiniteScroll from 'react-infinite-scroll-component'; 17 | 18 | import * as gtag from '../../../lib/gtag'; 19 | import Axios from 'axios'; 20 | import ChromaToast from '../../BaseComponents/ChromaToast'; 21 | 22 | const ModalTabItem = ({ children }) => { 23 | return ( 24 | 31 | {children} 32 | 33 | ); 34 | }; 35 | 36 | const DonateTab = ({ ...props }) => { 37 | const [isRedirectedFromDetail, setIsRedirectedFromDetail] = useState(false); 38 | 39 | const [currentPage, setCurrentPage] = useState(1); 40 | const [donationHistoryData, setDonationHistoryData] = useState([]); 41 | const [hasMore, setHasMore] = useState(true); 42 | 43 | const { username, modalUsernameShown } = useContext(DonateContext); 44 | 45 | const toast = useToast(); 46 | 47 | const sortBy = 'desc'; 48 | const orderBy = 'created_at'; 49 | 50 | const ScrollLoading = () => ( 51 |

Loading...

52 | ); 53 | 54 | const ScrollEnding = () => ( 55 |

Yay! You have seen it all

56 | ); 57 | 58 | const getDonationHistory = async (username) => { 59 | gtag.event({ 60 | action: 'Donate Check History', 61 | category: 'Donate', 62 | label: 'Donate Label', 63 | }); 64 | 65 | try { 66 | const result = await Axios({ 67 | url: `/api/donate-history?username=${username}&page=${currentPage}&sort_by=${sortBy}&order_by=${orderBy}`, 68 | method: 'GET', 69 | }); 70 | 71 | setCurrentPage(currentPage + 1); 72 | setDonationHistoryData((oldData) => { 73 | return [...oldData, ...result.data.data]; 74 | }); 75 | setHasMore(currentPage !== result.data.meta.total_page); 76 | } catch (error) { 77 | toast({ 78 | isClosable: true, 79 | duration: null, 80 | position: 'top-right', 81 | render: () => { 82 | return ( 83 | 87 | ); 88 | }, 89 | }); 90 | } 91 | }; 92 | 93 | useEffect(() => { 94 | if (username === '') return; 95 | if (modalUsernameShown) return; 96 | getDonationHistory(username); 97 | }, [username, modalUsernameShown]); 98 | 99 | return ( 100 | 101 | 102 | Donasi 103 | Cek Transaksi 104 | 105 | 106 | 107 | 108 | 109 | 110 | {donationHistoryData.length > 0 && ( 111 | getDonationHistory(username)} 115 | hasMore={hasMore} 116 | loader={} 117 | style={{ display: 'flex', flexDirection: 'column', gridGap: 8 }} 118 | endMessage={} 119 | > 120 | {donationHistoryData.map((data, idx) => ( 121 | 122 | ))} 123 | 124 | )} 125 | 126 | 127 | 128 | ); 129 | }; 130 | 131 | export default DonateTab; 132 | -------------------------------------------------------------------------------- /components/Homepage/BannerSection/index.jsx: -------------------------------------------------------------------------------- 1 | import { Box, Container, Flex, Text, useToast } from '@chakra-ui/react'; 2 | import copy from 'copy-to-clipboard'; 3 | import React from 'react'; 4 | import { ChromaButton, typesList } from '../../BaseComponents/ChromaButton'; 5 | import ChromaToast from '../../BaseComponents/ChromaToast'; 6 | 7 | const BannerSection = () => { 8 | const toast = useToast(); 9 | return ( 10 | <> 11 | 23 | 24 | 29 | 34 | mau mulai petualangan? 35 |
36 | lebih seru di chroma mc 37 |
38 | 44 | Nggak penting gimana caramu dan apa tujuanmu main.{' '} 45 | 46 | Chroma mc selalu bisa kasih kamu cerita yang berbeda 47 | 48 | 49 | { 53 | copy('mc.chroma-gaming.xyz'); 54 | toast({ 55 | duration: 1500, 56 | position: 'top-right', 57 | render: () => { 58 | return ( 59 | 63 | ); 64 | }, 65 | }); 66 | }} 67 | > 68 | Mainkan Sekarang 69 | 70 |
71 |
72 |
73 | 74 | ); 75 | }; 76 | 77 | export default BannerSection; 78 | -------------------------------------------------------------------------------- /components/Homepage/DonateSection/index.jsx: -------------------------------------------------------------------------------- 1 | import { Box, Container, Flex, Text } from '@chakra-ui/react'; 2 | import React from 'react'; 3 | import { ChromaButton, typesList } from '../../BaseComponents/ChromaButton'; 4 | 5 | const DonateSection = () => { 6 | return ( 7 | 19 | 20 | 25 | {/* TODO: Add background image */} 26 | 27 | 28 | 29 | 35 | Donasi 36 | 37 | 44 | Kami bisa sejauh ini juga 45 |
46 | karena dukunganmu! 47 |
48 | 54 | Donasi mulai dari 10.000 untuk nikmati fitur-fitur eksklusif 55 | dari kami. Atau beri vote dan dapatkan random drop setiap hari. 56 | 57 | 62 | 63 | Mulai Berdonasi 64 | 65 | 71 | Vote Sekarang 72 | 73 | 74 |
75 |
76 |
77 |
78 |
79 | ); 80 | }; 81 | 82 | export default DonateSection; 83 | -------------------------------------------------------------------------------- /components/Homepage/GameModeSection/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Container, 4 | keyframes, 5 | Flex, 6 | Image, 7 | SimpleGrid, 8 | Text, 9 | } from '@chakra-ui/react'; 10 | import Axios from 'axios'; 11 | import React, { useEffect, useState } from 'react'; 12 | 13 | const fadeIn = keyframes` 14 | 0% { opacity:0; } 15 | 100% { opacity:1; } 16 | `; 17 | 18 | const GameCardMapValue = [ 19 | { 20 | image: '/img/landing-page-skyblock.png', 21 | title: 'Sky Block', 22 | subtitle: 'Semi RPG', 23 | description: 24 | 'Sudah hebat dengan pola mining yang gitu-gitu aja? Coba uji skillmu dengan resouce terbatas di pulau kecil yang menantang', 25 | }, 26 | { 27 | image: '/img/landing-page-survival.png', 28 | title: 'Survival', 29 | subtitle: 'Semi Vanilla', 30 | description: 31 | 'Klaim tanah kekuasaanmu, ambil semua diamond yang ada, jual dipasar untuk modal berpetualang di dunia minecraft 1.17', 32 | }, 33 | { 34 | image: '/img/landing-page-minigame.png', 35 | title: 'Minigames', 36 | subtitle: 'Mechanic Based', 37 | description: 38 | 'Ketika grinding mulai terasa membosankan uji mekanik permainanmu melalui beragam minigames yang seru', 39 | }, 40 | ]; 41 | 42 | const GameCardItem = (props) => { 43 | return ( 44 | <> 45 | 46 | 47 | 53 | 54 | 60 | {props.title} | {props.subtitle} 61 | 62 | 67 | {props.description} 68 | 69 | 70 | 71 | ); 72 | }; 73 | 74 | const GameModeSection = () => { 75 | const [serverRank, setServerRank] = useState(0); 76 | const [vote, setVote] = useState(0); 77 | const [playerOnline, setPlayerOnline] = useState(0); 78 | const [maxPlayer, setMaxPlayer] = useState(0); 79 | const [changeContent, setChangeContent] = useState(false); 80 | 81 | const fetchData = async () => { 82 | const result = await Axios({ 83 | url: '/api/server', 84 | method: 'GET', 85 | headers: { 86 | 'Content-Type': 'application/json', 87 | }, 88 | }); 89 | setServerRank(result.data.rank ?? 0); 90 | setVote(result.data.votes ?? 0); 91 | setPlayerOnline(result.data.players ?? 0); 92 | setMaxPlayer(result.data.maxplayers ?? 0); 93 | }; 94 | 95 | useEffect(() => { 96 | fetchData(); 97 | 98 | setInterval(() => { 99 | fetchData(); 100 | }, 3000); 101 | }, []); 102 | 103 | useEffect(() => { 104 | setTimeout(() => { 105 | setChangeContent(!changeContent); 106 | }, 3000); 107 | }, [changeContent]); 108 | 109 | return ( 110 | 111 | 112 | 113 | 119 | Mode Permainan 120 | 121 | 127 | 128 | 133 | Beragam mode permainan 134 |
135 | bye-bye rasa bosan 136 |
137 |
138 | 142 | 147 | 148 | 153 | {changeContent 154 | ? `Peringkat server ${serverRank}` 155 | : `${playerOnline} Player Online`} 156 | 157 | 162 | {changeContent 163 | ? `${vote} Total Vote` 164 | : `Maximum ${maxPlayer} Player`} 165 | 166 | 167 | 168 | 177 | 178 | 179 | 180 |
181 | 182 | {GameCardMapValue.map((item, index) => ( 183 | 184 | ))} 185 | 186 |
187 |
188 |
189 | ); 190 | }; 191 | 192 | export default GameModeSection; 193 | -------------------------------------------------------------------------------- /components/Homepage/HelpSection/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Container, 4 | Flex, 5 | Image, 6 | Link, 7 | Text, 8 | VStack, 9 | } from '@chakra-ui/react'; 10 | import React from 'react'; 11 | 12 | const HelpItem = ({ children }) => { 13 | return ( 14 | 20 | 21 | {children} 22 | 23 | 24 | ); 25 | }; 26 | 27 | const HelpSection = () => { 28 | return ( 29 | 37 | 38 | 39 | 44 | 45 | 51 | Bantuan 52 | 53 | 60 | Ketemu yang bikin bingung pas main? 61 | 62 | 67 | Tenang kita ada wiki buat yang mau baca dan cari tahu sendiri, 68 | atau hit aja di community discord kami (budayakan membaca). 69 | Terakhir kalau ada ide atau saran jangan lupa drop ya 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Channel{' '} 81 | 85 | Discord 86 | 87 | 88 | , Cari temen mabar 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | Lihat Server{' '} 98 | 99 | Wiki 100 | 101 | 102 | , Lebih detail & mandiri 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | Punya{' '} 112 | 113 | Saran 114 | 115 | 116 | ? Drop dulu, hasut kemudian 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | ); 126 | }; 127 | 128 | export default HelpSection; 129 | -------------------------------------------------------------------------------- /components/Homepage/ReportSection/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Container, 4 | Flex, 5 | FormControl, 6 | FormLabel, 7 | Input, 8 | Text, 9 | Textarea, 10 | Button, 11 | } from '@chakra-ui/react'; 12 | import React from 'react'; 13 | import { ChromaButton, typesList } from '../../BaseComponents/ChromaButton'; 14 | import ChromaDropdown from '../../BaseComponents/ChromaDropdown'; 15 | 16 | const ServerOptions = [ 17 | { 18 | value: 'Vanilla', 19 | label: 'Vanilla', 20 | }, 21 | { 22 | value: 'SkyBlock', 23 | label: 'SkyBlock', 24 | }, 25 | ]; 26 | 27 | const ReportTypeOptions = [ 28 | { 29 | value: 'Cheat', 30 | label: 'Cheat', 31 | }, 32 | { 33 | value: 'Grief', 34 | label: 'Grief', 35 | }, 36 | { 37 | value: 'Bug', 38 | label: 'Bug', 39 | }, 40 | { 41 | value: 'Other', 42 | label: 'Lainnya', 43 | }, 44 | ]; 45 | 46 | const ReportSection = () => { 47 | return ( 48 | 59 | 60 | 64 | 70 | LAPORAN 71 | 72 | 78 | Cheating, griefing, bullying, aneh, dan mengganggu.{' '} 79 | Laporkan! 80 | 81 | 82 | 83 | Jenis Temuan 84 | 85 | 86 | 87 | 88 | 89 | Ketemu di server mana? 90 | 91 | 92 | 93 | 94 | 95 | Username Minecraftmu 96 | 97 | 104 | 105 | 106 | 107 | Ceritakan apa yang terjadi 108 | 109 |