Skip to content

Commit

Permalink
Dapp add devote (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xExp-po authored Sep 20, 2024
1 parent 32ba7ca commit 360bce2
Show file tree
Hide file tree
Showing 11 changed files with 584 additions and 38 deletions.
4 changes: 4 additions & 0 deletions dapp/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ PUBLIC_SOROBAN_RPC_URL="https://soroban-testnet.stellar.org:443"

PUBLIC_TANSU_CONTRACT_ID="CCYM5OC6RTMEUHRK2BRU5YX4G4O745DPLPU4EXVTRCUN7JRJJWXEEXAB"
PUBLIC_SOROBAN_DOMAIN_CONTRACT_ID="CADDH3WW3EHDEUY4HIQUAZHRPCFQFL4MZIEZBFUIIHJAXZNLQWVC6DV4"
PUBLIC_TANSU_OWNER_ID="GCMFQP44AR32S7IRIUKNOEJW5PNWOCLRHLQWSHUCSV4QZOMUXZOVA7Q2"

PUBLIC_DEFAULT_FEE=100
PUBLIC_DEFAULT_TIMEOUT=30

SOROBAN_ACCOUNT="alice"
SOROBAN_NETWORK="testnet"
2 changes: 2 additions & 0 deletions dapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
"@astrojs/check": "^0.9.3",
"@astrojs/react": "^3.6.2",
"@astrojs/tailwind": "^5.1.0",
"@creit.tech/sorobandomains-sdk": "^0.1.2",
"@creit.tech/stellar-wallets-kit": "^1.0.0",
"@nanostores/react": "^0.7.3",
"@stellar/stellar-sdk": "^12.3.0",
"astro": "^4.2.4",
"install": "^0.13.0",
"js-sha3": "^0.9.3",
Expand Down
238 changes: 238 additions & 0 deletions dapp/src/components/DonateModal.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
---
import Loading from "./utils/Loading.astro";
---

<div
id="donate-modal"
class="fixed inset-0 bg-black bg-opacity-50 items-center justify-center z-50 hidden"
>
<div
class="bg-white px-4 sm:px-8 md:px-12 py-8 rounded-2xl relative w-[530px] max-w-[90%]"
>
<button
id="close-donate-modal"
class="absolute top-3 right-3 text-zinc-600 hover:text-zinc-600"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>

<div class="flex flex-col space-y-3 sm:space-y-6 md:space-y-8">
<div>
<h2 id="donate-modal-title" class="text-xl sm:text-2xl font-bold bg-lime py-1 sm:py-2 px-2 rounded-xl w-min">Contribute</h2>
</div>

<div class="flex flex-col gap-3 w-full">
<div class="flex w-full">
<button class="amount-button flex-1 bg-zinc-800 border border-zinc-800 text-lg sm:text-xl md:text-2xl font-semibold text-white py-1 rounded-l-lg">10 XLM</button>
<button class="amount-button flex-1 bg-zinc-200 border border-zinc-300 text-lg sm:text-xl md:text-2xl font-semibold text-zinc-600 py-1">100 XLM</button>
<button class="amount-button flex-1 bg-zinc-200 border border-zinc-300 text-lg sm:text-xl md:text-2xl font-semibold text-zinc-600 py-1 rounded-r-lg">Other</button>
</div>
<div class="w-full h-[30px] sm:h-[38px]">
<div id="amount-input-container" class="hidden items-center">
<div class="flex items-center relative">
<span class="absolute left-2 sm:left-3 sm:py-0.5 pr-1 border-r-2 border-zinc-600">XLM</span>
<input
id="amount-input"
type="number"
class="w-[120px] sm:w-40 flex-1 border rounded-lg pl-12 sm:pl-14 pr-3 py-0.5 sm:py-1 text-base sm:text-lg text-right"
value="10"
/>
</div>
<div class="flex w-full justify-center items-center">
<p class="text-sm sm:text-base">Minimum amount: 1 XLM</p>
</div>
</div>
</div>
</div>


<textarea id="donate-message" placeholder="Say something nice..." rows="4" class="w-full border border-zinc-400 bg-zinc-200 rounded-xl p-2 resize-none focus:outline-none"></textarea>

<div class="flex items-center">
<span class="mr-2 flex items-center">
Platform tip:
<span class="relative group ml-1">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24">
<rect width="24" height="24" rx="2" fill="#3b82f6" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M12.5 16h-1v-4h-1m1-4h.01M12 8v.01" stroke="white" fill="none" />
</svg>
<div class="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 hidden group-hover:block w-max max-w-[330px] sm:max-w-none">
<div id="donate-tip-popup" class="bg-zinc-800 text-white text-sm py-2 px-4 rounded-lg shadow-lg relative">
Help us run the Tansu platform sustainability
<div class="absolute -bottom-1 left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-zinc-800"></div>
</div>
</div>
</span>
</span>
<div class="flex items-center relative">
<span class="absolute left-2 sm:left-3 sm:py-0.5 pr-1 border-r-2 border-zinc-600">XLM</span>
<input
id="tip-amount-input"
type="number"
class="w-28 sm:w-36 flex-1 border rounded-lg pl-12 sm:pl-14 pr-3 py-0.5 sm:py-1 text-sm sm:text-base text-right"
value=0
/>
</div>
</div>

<div class="flex justify-center">
<button
id="contribute-button"
class="bg-zinc-800 text-white text-base sm:text-lg py-2 rounded-xl px-8 sm:px-12 w-max"
>
<span id="contribute-text">Contribute to <span id="project-name"></span>.xlm</span>
<div id="contribute-loader" class="hidden">
<Loading theme="dark" />
</div>
</button>
</div>
</div>
</div>
</div>

<script>
import { sendXLM } from "../service/PaymentService";
import { getAddressFromDomain } from "../service/SorobanDomainContractService";

document.addEventListener("astro:page-load", () => {
const amountButtons = document.querySelectorAll('.amount-button');
const amountInputContainer = document.getElementById('amount-input-container');
const amountInput = document.getElementById('amount-input') as HTMLInputElement;
const platformTipInput = document.getElementById('tip-amount-input') as HTMLInputElement;
let selectedAmount = 10; // Default amount

amountButtons.forEach((button) => {
button.addEventListener('click', () => {
amountButtons.forEach(btn => btn.classList.remove('bg-zinc-800', 'border-zinc-800', 'text-white'));
amountButtons.forEach(btn => btn.classList.add('bg-zinc-200', 'border-zinc-300', 'text-zinc-600'));
button.classList.remove('bg-zinc-200','border-zinc-300', 'text-zinc-600');
button.classList.add('bg-zinc-800','border-zinc-800', 'text-white');

const buttonText = button.textContent?.trim();
if (buttonText === 'Other') {
amountInputContainer?.classList.remove('hidden');
amountInputContainer?.classList.add('flex');
selectedAmount = parseFloat(amountInput.value) || 0;
} else {
amountInputContainer?.classList.remove('flex');
amountInputContainer?.classList.add('hidden');
selectedAmount = buttonText === '100 XLM' ? 100 : 10;
}
});
});

const modal = document.getElementById('donate-modal');
const closeButton = document.getElementById('close-donate-modal');
const modalContent = modal?.querySelector('div');

if (closeButton && modal) {
closeButton.addEventListener('click', () => {
modal.classList.add('hidden');
});

// Add click event listener to the modal
modal.addEventListener('click', (event) => {
if (event.target === modal) {
modal.classList.add('hidden');
}
});

// Prevent closing when clicking inside the modal content
modalContent?.addEventListener('click', (event) => {
event.stopPropagation();
});
}

const contributeButton = document.getElementById('contribute-button');
const contributeText = document.getElementById('contribute-text');
const contributeLoader = document.getElementById('contribute-loader');

if (contributeButton && contributeText && contributeLoader) {
contributeButton.addEventListener('click', async () => {
// Show loader and hide text
contributeText.classList.add('hidden');
contributeLoader.classList.remove('hidden');

const amount = amountInputContainer?.classList.contains('flex')
? parseFloat(amountInput.value) || 0
: selectedAmount;
const tipAmount = parseFloat(platformTipInput.value) || 0;

if (amount < 1) {
amountInput.style.border = '2px solid red';
const minAmountText = document.querySelector('#amount-input-container p') as HTMLElement;
if (minAmountText) {
minAmountText.style.color = 'red';
}
setTimeout(() => {
amountInput.style.border = '';
if (minAmountText) {
minAmountText.style.color = '';
}
}, 2000);
// Hide loader and show text again
contributeLoader?.classList.add('hidden');
contributeText?.classList.remove('hidden');
return;
}

const donateMessage = (document.getElementById('donate-message') as HTMLTextAreaElement).value;

try {
console.log("fetching domain Info...");
const domainInfo = await getAddressFromDomain('tansu');
if (domainInfo && !domainInfo.error && typeof domainInfo.message === 'object' && 'owner' in domainInfo.message.value) {
const domainOwnerAddress = domainInfo.message.value.owner;
const payment = await sendXLM(amount.toString(), domainOwnerAddress as string, tipAmount.toString(), donateMessage);
if (payment) {
alert("You successfully donated.");
if (modal) {
modal.classList.add('hidden');
}
} else {
alert("Donation failed.");
}
} else {
alert("Cannot read domain information.");
}
} catch (error) {
console.error("Error during contribution:", error);
alert("An error occurred during the contribution process.");
} finally {
// Hide loader and show text again
contributeLoader?.classList.add('hidden');
contributeText?.classList.remove('hidden');
}
});
}

// Function to allow only positive integers
const allowOnlyPositiveIntegers = (event: KeyboardEvent) => {
if (!/[0-9]/.test(event.key) && event.key !== 'Backspace' && event.key !== 'Delete' && event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') {
event.preventDefault();
}
};

// Add event listeners to both input fields
[amountInput, platformTipInput].forEach(input => {
input.addEventListener('keydown', allowOnlyPositiveIntegers);
input.addEventListener('input', () => {
input.value = input.value.replace(/[^0-9]/g, '');
});
});
});
</script>
Loading

0 comments on commit 360bce2

Please sign in to comment.