SettingsDomain.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import { useFormState } from "react-use-form-state";
  2. import { Flex } from "reflexbox/styled-components";
  3. import React, { FC, useState } from "react";
  4. import styled from "styled-components";
  5. import { useStoreState, useStoreActions } from "../../store";
  6. import { Domain } from "../../store/settings";
  7. import { errorMessage } from "../../utils";
  8. import { useMessage } from "../../hooks";
  9. import Text, { H2, Span } from "../Text";
  10. import { Colors } from "../../consts";
  11. import { TextInput } from "../Input";
  12. import { Button } from "../Button";
  13. import { Col } from "../Layout";
  14. import Table from "../Table";
  15. import Modal from "../Modal";
  16. import Icon from "../Icon";
  17. const Th = styled(Flex).attrs({ as: "th", py: 3, px: 3 })`
  18. font-size: 15px;
  19. `;
  20. const Td = styled(Flex).attrs({ as: "td", py: 12, px: 3 })`
  21. font-size: 15px;
  22. `;
  23. const SettingsDomain: FC = () => {
  24. const { saveDomain, deleteDomain } = useStoreActions(s => s.settings);
  25. const [domainToDelete, setDomainToDelete] = useState<Domain>(null);
  26. const [deleteLoading, setDeleteLoading] = useState(false);
  27. const domains = useStoreState(s => s.settings.domains);
  28. const [message, setMessage] = useMessage(2000);
  29. const [loading, setLoading] = useState(false);
  30. const [modal, setModal] = useState(false);
  31. const [formState, { label, text }] = useFormState<{
  32. address: string;
  33. homepage: string;
  34. }>(null, { withIds: true });
  35. const onSubmit = async e => {
  36. e.preventDefault();
  37. setLoading(true);
  38. try {
  39. await saveDomain(formState.values);
  40. } catch (err) {
  41. setMessage(err?.response?.data?.error || "Couldn't add domain.");
  42. }
  43. formState.clear();
  44. setLoading(false);
  45. };
  46. const closeModal = () => {
  47. setDomainToDelete(null);
  48. setModal(false);
  49. };
  50. const onDelete = async () => {
  51. setDeleteLoading(true);
  52. await deleteDomain(domainToDelete.id).catch(err =>
  53. setMessage(errorMessage(err, "Couldn't delete the domain."))
  54. );
  55. setMessage("Domain has been deleted successfully.", "green");
  56. closeModal();
  57. setDeleteLoading(false);
  58. };
  59. return (
  60. <Col alignItems="flex-start" maxWidth="100%">
  61. <H2 mb={4} bold>
  62. Custom domain
  63. </H2>
  64. <Text mb={3}>
  65. You can set a custom domain for your short URLs, so instead of{" "}
  66. <b>kutt.it/shorturl</b> you can have <b>example.com/shorturl.</b>
  67. </Text>
  68. <Text mb={4}>
  69. Point your domain A record to <b>192.64.116.170</b> then add the domain
  70. via form below:
  71. </Text>
  72. {domains.length ? (
  73. <Table my={3} scrollWidth="550px">
  74. <thead>
  75. <tr>
  76. <Th width={2 / 5}>Domain</Th>
  77. <Th width={2 / 5}>Homepage</Th>
  78. <Th width={1 / 5}></Th>
  79. </tr>
  80. </thead>
  81. <tbody>
  82. {domains.map(d => (
  83. <tr key={d.address}>
  84. <Td width={2 / 5}>{d.address}</Td>
  85. <Td width={2 / 5}>
  86. {d.homepage || process.env.DEFAULT_DOMAIN}
  87. </Td>
  88. <Td width={1 / 5} justifyContent="center">
  89. <Icon
  90. as="button"
  91. name="trash"
  92. stroke={Colors.TrashIcon}
  93. strokeWidth="2.5"
  94. backgroundColor={Colors.TrashIconBg}
  95. py={0}
  96. px={0}
  97. size={[23, 24]}
  98. p={["4px", "5px"]}
  99. onClick={() => {
  100. setDomainToDelete(d);
  101. setModal(true);
  102. }}
  103. />
  104. </Td>
  105. </tr>
  106. ))}
  107. </tbody>
  108. </Table>
  109. ) : (
  110. <Col
  111. alignItems="flex-start"
  112. onSubmit={onSubmit}
  113. width={1}
  114. as="form"
  115. my={[3, 4]}
  116. >
  117. <Flex width={1} flexDirection={["column", "row"]}>
  118. <Col mr={[0, 2]} mb={[3, 0]} flex="0 0 auto">
  119. <Text
  120. {...label("address")}
  121. as="label"
  122. mb={[2, 3]}
  123. fontSize={[15, 16]}
  124. bold
  125. >
  126. Domain
  127. </Text>
  128. <TextInput
  129. {...text("address")}
  130. placeholder="example.com"
  131. maxWidth="240px"
  132. required
  133. />
  134. </Col>
  135. <Col ml={[0, 2]} flex="0 0 auto">
  136. <Text
  137. {...label("homepage")}
  138. as="label"
  139. mb={[2, 3]}
  140. fontSize={[15, 16]}
  141. bold
  142. >
  143. Homepage (optional)
  144. </Text>
  145. <TextInput
  146. {...text("homepage")}
  147. placeholder="Homepage URL"
  148. flex="1 1 auto"
  149. maxWidth="240px"
  150. />
  151. </Col>
  152. </Flex>
  153. <Button type="submit" color="purple" mt={[24, 3]} disabled={loading}>
  154. <Icon name={loading ? "spinner" : "plus"} mr={2} stroke="white" />
  155. {loading ? "Setting..." : "Set domain"}
  156. </Button>
  157. </Col>
  158. )}
  159. <Text color={message.color}>{message.text}</Text>
  160. <Modal id="delete-custom-domain" show={modal} closeHandler={closeModal}>
  161. <H2 mb={24} textAlign="center" bold>
  162. Delete domain?
  163. </H2>
  164. <Text textAlign="center">
  165. Are you sure do you want to delete the domain{" "}
  166. <Span bold>"{domainToDelete && domainToDelete.address}"</Span>?
  167. </Text>
  168. <Flex justifyContent="center" mt={44}>
  169. {deleteLoading ? (
  170. <>
  171. <Icon name="spinner" size={20} stroke={Colors.Spinner} />
  172. </>
  173. ) : (
  174. <>
  175. <Button color="gray" mr={3} onClick={closeModal}>
  176. Cancel
  177. </Button>
  178. <Button color="red" ml={3} onClick={onDelete}>
  179. <Icon name="trash" stroke="white" mr={2} />
  180. Delete
  181. </Button>
  182. </>
  183. )}
  184. </Flex>
  185. </Modal>
  186. </Col>
  187. );
  188. };
  189. export default SettingsDomain;