Skip to content
This repository has been archived by the owner on May 26, 2024. It is now read-only.

Feature page stuck on "Loading" #44

Closed
arkdev22 opened this issue Jan 15, 2024 · 4 comments
Closed

Feature page stuck on "Loading" #44

arkdev22 opened this issue Jan 15, 2024 · 4 comments

Comments

@arkdev22
Copy link

Issue Summary:
I'm encountering an issue with my custom feature. The problem arises when I try to configure the feature, as it gets stuck on "Loading."

KDOAKDA

Code Files:

  • features.tsx in config folder
  • custom-types.tsx in config folder
  • FruitStocksFeature.tsx in config > use-features folder
  • Backend server implementation

Description:
I've created a custom feature called "Fruit Stocks" for my bot. The feature itself works well, including the enable feature button. However, when attempting to configure the feature, it gets stuck on "Loading."

features.tsx

config > features.tsx

import { Icon } from '@chakra-ui/react';
import { FaAppleAlt } from 'react-icons/fa';
import { FeaturesConfig } from './types';
import { provider } from '@/config/translations/provider';
import { createI18n } from '@/utils/i18n';
import { useFruitStocksFeature } from "./use-features/FruitStocksFeature";

/**
 * Support i18n (Localization)
 */
const { T } = createI18n(provider, {
  en: {
    fruitStocks: "Fruit Stocks",
    'fruitStocks description': 'Blox Fruit\'s stock notifier',
  },
});

/**
 * Define information for each features
 *
 * There is an example:
 */
export const features: FeaturesConfig = {
  fruitStocks: {
    name: <T text="fruitStocks" />,
    description: <T text="fruitStocks description" />,
    icon: <Icon as={FaAppleAlt} />,
    useRender: useFruitStocksFeature,
  }
};

custom-types.tsx

config > types

/***
 * Custom types that should be configured by developer
 ***/

import { z } from 'zod';
import { GuildInfo } from './types';

export type CustomGuildInfo = GuildInfo & {};

/**
 * Define feature ids and it's option types
 */
export type CustomFeatures = {
  fruitStocks: FruitStocksFeature;
};

/**
 * Define feature ids and it's option types
 */
export type FruitStocksFeature = {
  channel?: string;
};

FruitStocksFeature.tsx

config > use-features
Note: use-feature is a folder that I made to store all of my custom features.

import { SimpleGrid } from '@chakra-ui/layout';
import { TextAreaForm } from '@/components/forms/TextAreaForm';
import { UseFormRender, FruitStocksFeature } from '@/config/types';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { ColorPickerForm, SmallColorPickerForm } from '@/components/forms/ColorPicker';
import { DatePickerForm } from '@/components/forms/DatePicker';
import { FilePickerForm } from '@/components/forms/FilePicker';
import { SwitchFieldForm } from '@/components/forms/SwitchField';
import { ChannelSelectForm } from '@/components/forms/ChannelSelect';

const schema = z.object({
  channel: z.string(),
  danger: z.boolean(),
});

type Input = z.infer<typeof schema>;

export const useFruitStocksFeature: UseFormRender<FruitStocksFeature> = (data, onSubmit) => {
  const { register, reset, handleSubmit, formState, control } = useForm<Input>({
    resolver: zodResolver(schema),
    shouldUnregister: false,
    defaultValues: {
      channel: data.channel,
      danger: false,
    },
  });

  console.log("HELLO FRUIT STOCKS")

  return {
    component: (
      <SimpleGrid columns={{ base: 1, lg: 2 }} gap={3}>
        <ChannelSelectForm
          control={{
            label: 'Channel',
            description: 'Where to send the welcome message',
          }}
          controller={{ control, name: 'channel' }}
        />
        <SwitchFieldForm
          control={{ label: 'Turn on', description: 'Enable something' }}
          controller={{
            control,
            name: 'danger',
          }}
        />
      </SimpleGrid>
    ),
    onSubmit: handleSubmit(async (e) => {
      const data = await onSubmit(
        JSON.stringify({
          channel: e.channel,
        })
      );

      reset(data);
    }),
    canSave: formState.isDirty,
    reset: () => reset(control._defaultValues),
  };
};

Backend Server Implementation

Note: This code is only the "listening" to a certain route and I have the backend server working. It is using express.js and is running alongside with my actual bot.

module.exports = (client, server, utils) => {
  server.get("/guilds/:id/features/fruitStocks", async (req, res) => {    
    try {
      console.log("trying to get")
      const guild = client.guilds.cache.get(req.params.id);
      const schema = await client.mongoose.schemas.guilds.findOne({ guildId: guild.id })

      if (!schema) {
        return res.status(404).json({ error: "Guild schema not found" });
      }

      const fruitStocks = schema.modules.fruitStocks;

      console.log("Im here")
      return { channel: "1180089709196738561" }
    } catch (error) {
      console.error(error);
      return res.status(500).json({ error: `Internal server error. ${error}` })
    }
  })
  
  server.post("/guilds/:id/features/fruitStocks", async (req, res) => {
    try {
      console.log("trying to post")
      await utils.checkPermission(req.session, req.params.id);

      const guild = client.guilds.cache.get(req.params.id);
      const schema = await client.mongoose.schemas.guilds.findOne({ guildId: guild.id })

      if (!schema) {
        return res.status(404).json({ error: "Guild schema not found" });
      }

      schema.modules.fruitStocks.enabled = true
      await schema.save()
      return "Success"
    } catch (error) {
      console.error(error);
      return res.status(500).json({ error: `Internal server error. ${error}` })
    }
  })

  server.delete("/guilds/:id/features/fruitStocks", async (req, res) => {
    try {
      console.log("trying to delete")
      await utils.checkPermission(req.session, req.params.id);

      const guild = client.guilds.cache.get(req.params.id);
      const schema = await client.mongoose.schemas.guilds.findOne({ guildId: guild.id })

      if (!schema) {
        return res.status(404).json({ error: "Guild schema not found" });
      }

      schema.modules.fruitStocks.enabled = false
      await schema.save()
      return "Success"
    } catch (error) {
      console.error(error);
      return res.status(500).json({ error: `Internal server error. ${error}` })
    }
  })

  server.patch("/guilds/:id/features/fruitStocks", async (req, res) => {
    try {
      console.log("trying to patch")
      await utils.checkPermission(req.session, req.params.id);

      const guild = client.guilds.cache.get(req.params.id);
      const schema = await client.mongoose.schemas.guilds.findOne({ guildId: guild.id })

      if (!schema) {
        return res.status(404).json({ error: "Guild schema not found" });
      }
    } catch (error) {
      console.error(error);
      return res.status(500).json({ error: `Internal server error. ${error}` })
    }
  })
}

Any Help Appreciated:

I would appreciate any guidance or assistance in resolving this issue. If more code files or information are needed, please let me know.

Thank you for your help!

@arkdev22
Copy link
Author

@fuma-nama Hello, can you assist me with this? Thank you.

@fuma-nama
Copy link
Owner

Check your devtools and see if any requests failed

@arkdev22
Copy link
Author

Check your devtools and see if any requests failed

No requests failed (404, etc), but I saw 2 requests for /guilds/:id/features/fruitStock. One with a status of 204, and the other with a status of pending.

@arkdev22
Copy link
Author

I fixed it by using res.status(200) instead of return "Success" as per the example backend.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants