The frontend for the project formerly known as signet, now known as beignet.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

180 行
5.5 KiB

  1. <template>
  2. <div>
  3. <section>
  4. <div class="title is-4 has-text-white-ter has-text-centered">Add Fund</div>
  5. <section class="section px-0 py-4">
  6. <div class="title is-5 has-text-white-ter">Post</div>
  7. <div class="control my-2">
  8. <input type="text"
  9. placeholder="Title" aria-label="Title" v-model="title">
  10. </div>
  11. <div class="control my-2">
  12. <textarea
  13. placeholder="Description" aria-label="Description" v-model="description">
  14. </textarea>
  15. </div>
  16. </section>
  17. <section class="section px-0 py-4">
  18. <div class="title is-5 has-text-white-ter">Wallet</div>
  19. <div class="control my-2">
  20. <input type="text"
  21. placeholder="Fund Wallet" aria-label="Fund Wallet" v-model="fundWallet">
  22. </div>
  23. <div class="control my-2">
  24. <input type="text"
  25. placeholder="Selling Wallet" aria-label="Selling Wallet" v-model="sellWallet">
  26. </div>
  27. <div class="control my-2">
  28. <input type="text"
  29. placeholder="Issuer Wallet" aria-label="Issuer Wallet" v-model="issuerWallet">
  30. </div>
  31. </section>
  32. <section class="section px-0 py-4">
  33. <div class="title is-5 has-text-white-ter">Fund</div>
  34. <div class="control my-2 is-flex is-justify-content-space-between">
  35. <input class="input is-normal mr-1 has-background-white has-text-black" type="text"
  36. placeholder="Asset Code" aria-label="Asset" v-model="asset">
  37. <input class="input is-normal mx-1 has-background-white has-text-black" type="text"
  38. placeholder="Memo" aria-label="Memo" v-model="memo">
  39. <input class="input is-normal ml-1 has-background-white has-text-black" type="number"
  40. placeholder="Min Contribution" aria-label="Min Contribution"
  41. v-model="minContribution">
  42. </div>
  43. </section>
  44. <section class="section px-0 py-4">
  45. <div class="title is-5 has-text-white-ter">Bonus Structure</div>
  46. <FundTierInput @save="saveBonuses"/>
  47. </section>
  48. <section class="section px-0 py-4">
  49. <div class="title is-5 has-text-white-ter">Queue</div>
  50. <EditQueue
  51. :new-member="constructFund()"
  52. @created="setQueueName"
  53. @selected="setQueueSelection"
  54. />
  55. </section>
  56. </section>
  57. <div class="buttons is-flex is-justify-content-end mt-5">
  58. <button
  59. :class="requesting ? 'is-loading' : ''"
  60. @click="submit"
  61. >Submit
  62. </button>
  63. </div>
  64. </div>
  65. </template>
  66. <script setup lang="ts">
  67. import SignetRequestController from '@/api/requests';
  68. import {
  69. Bonus,
  70. CreateQueueResponse,
  71. } from '@/api/types';
  72. import { ref } from 'vue';
  73. import { useRouter } from 'vue-router';
  74. import FundTierInput from '@/components/FundTierInput.vue';
  75. import EditQueue from '@/components/EditQueue.vue';
  76. import {
  77. createQueue,
  78. createRewardFund,
  79. } from '@/api/composed';
  80. import { sanitize } from '@/lib/helpers';
  81. const router = useRouter();
  82. document.title = 'Beignet - Add Fund';
  83. const controller = new SignetRequestController();
  84. const title = ref('');
  85. const description = ref('');
  86. const fundWallet = ref('');
  87. const sellWallet = ref('');
  88. // const fundSecret = ref('');
  89. const issuerWallet = ref('');
  90. const asset = ref('');
  91. const memo = ref('');
  92. const minContribution = ref(undefined as number | undefined);
  93. const queueName = ref(undefined as string | undefined);
  94. const queueSelection = ref(undefined as number | undefined);
  95. // TODO: figure out why the above vars are not reactive
  96. const setQueueName = (name: string) => {
  97. queueName.value = name;
  98. };
  99. const setQueueSelection = (val: number) => {
  100. queueSelection.value = val;
  101. };
  102. const bonuses = ref([] as Bonus[]);
  103. const saveBonuses = (evt: Bonus[]) => {
  104. bonuses.value = evt;
  105. };
  106. const doCreateQueue = async () => {
  107. if (!queueName.value) return null;
  108. const resp = ref(undefined as CreateQueueResponse | undefined);
  109. resp.value = await createQueue(queueName.value) ?? undefined;
  110. if (resp.value?.id) {
  111. return resp.value?.id;
  112. }
  113. return null;
  114. };
  115. const constructFund = () => ({
  116. asset: asset.value,
  117. fundWallet: sanitize(fundWallet.value),
  118. sellingWallet: sanitize(sellWallet.value),
  119. issuerWallet: sanitize(issuerWallet.value),
  120. memo: sanitize(memo.value),
  121. minContribution: minContribution.value,
  122. title: sanitize(title.value),
  123. description: sanitize(description.value),
  124. bonuses: bonuses.value,
  125. queueID: null,
  126. });
  127. const requesting = ref(false);
  128. const submit = async () => {
  129. if (!minContribution.value) return;
  130. if (!/^[0-9]+$/.test(minContribution.value.toString())) return;
  131. if (!requesting.value) {
  132. requesting.value = true;
  133. const forQueue = ref(undefined as null | number | undefined);
  134. if (queueSelection.value === -1) {
  135. forQueue.value = await doCreateQueue();
  136. } else {
  137. forQueue.value = queueSelection.value;
  138. }
  139. const resp = await createRewardFund(
  140. asset.value,
  141. sanitize(fundWallet.value),
  142. sanitize(sellWallet.value),
  143. sanitize(issuerWallet.value),
  144. sanitize(memo.value),
  145. minContribution.value,
  146. sanitize(title.value),
  147. sanitize(description.value),
  148. bonuses.value,
  149. forQueue.value,
  150. );
  151. requesting.value = false;
  152. if (!resp) throw new Error('Could not get response for fund creation');
  153. if (resp.success) {
  154. await router.push('/');
  155. }
  156. }
  157. };
  158. </script>
  159. <style scoped lang="stylus">
  160. input::placeholder, textarea::placeholder
  161. color #7d7d7d
  162. </style>