Search
Search

Transaction: 5bAHNfm...jXC3

Signed by
Receiver
Status
Succeeded
Transaction Fee
0.00169 
Deposit Value
0.0256 
Gas Used
17 Tgas
Attached Gas
300 Tgas
Created
March 01, 2024 at 7:32:51am
Hash
5bAHNfmKTMCT4wNNLr3FQqV6hiDjVxzSJNuc89awjXC3

Actions

Called method: 'set' in contract: social.near
Arguments:
{ "data": { "buildhub.near": { "widget": { "events.Calendar": { "": "const { Button } = VM.require(\"buildhub.near/widget/components\") || {\n Button: () => <></>,\n};\n\nconst { fetchThings } = VM.require(\n \"buildhub.near/widget/lib.everything-sdk\"\n) || {\n fetchThings: () => {},\n};\n\nconst StyledToolbar = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n border: 1px solid var(--stroke-color, rgba(255, 255, 255, 0.2));\n padding: 16px 24px;\n margin-bottom: 24px;\n\n background: var(--bg-1, #000000);\n\n color: var(--text-color, #fff);\n font-size: 18px;\n\n .section {\n display: flex;\n align-items: center;\n flex-basis: 0;\n flex-grow: 1;\n }\n\n .date-changer {\n all: unset;\n cursor: pointer;\n }\n\n @media screen and (max-width: 768px) {\n flex-direction: column;\n gap: 1rem;\n }\n`;\n\n// implement event fetching and filtering\n\nconst [selectedView, setSelectedView] = useState(\"month\");\nconst [currentDate, setCurrentDate] = useState(new Date());\n\nconst [showCreateModal, setShowCreateModal] = useState(false);\nconst toggleCreateModal = () => setShowCreateModal(!showCreateModal);\n\nconst [showFilterModal, setShowFilterModal] = useState(false);\nconst toggleFilterModal = () => setShowFilterModal(!showFilterModal);\n\nconst [filters, setFilters] = useState({});\n\nconst dateString = currentDate.toLocaleString(\"en-us\", {\n month: \"long\",\n year: \"numeric\",\n});\n\nconst handleMonthChange = (change) => {\n const date = currentDate;\n date.setMonth(date.getMonth() + change);\n setCurrentDate(date);\n};\n\nconst Toolbar = () => {\n return (\n <StyledToolbar>\n <div className=\"section gap-3\">\n <span>{dateString}</span>\n <button className=\"date-changer\" onClick={() => handleMonthChange(-1)}>\n <i className=\"bi bi-chevron-left\"></i>\n </button>\n <button className=\"date-changer\" onClick={() => handleMonthChange(1)}>\n <i className=\"bi bi-chevron-right\"></i>\n </button>\n </div>\n <div className=\"section gap-1 justify-content-center\">\n <Button\n variant={selectedView === \"month\" ? \"secondary\" : \"outline\"}\n onClick={() => setSelectedView(\"month\")}\n >\n Month\n </Button>\n <Button\n variant={selectedView === \"list\" ? \"secondary\" : \"outline\"}\n onClick={() => setSelectedView(\"list\")}\n >\n List\n </Button>\n </div>\n <div className=\"section justify-content-end\" style={{ gap: 10 }}>\n <Button variant=\"outline\" onClick={() => setShowFilterModal(true)}>\n Filter By\n </Button>\n {context.accountId && (\n <Button variant=\"primary\" onClick={() => setShowCreateModal(true)}>\n Add Event\n </Button>\n )}\n </div>\n </StyledToolbar>\n );\n};\n\nconst app = props.app ?? \"every\";\nconst thing = props.thing ?? \"event\";\nconst events = fetchThings(app, thing);\n\nconst filterEvents = () => {\n let filteredEvents = events;\n\n // handle date from filter\n if (filters.from) {\n filteredEvents = filteredEvents.filter((event) => {\n return new Date(event.start) >= new Date(filters.from);\n });\n }\n\n // handle date to filter\n if (filters.to) {\n filteredEvents = filteredEvents.filter((event) => {\n return new Date(event.start) <= new Date(filters.to);\n });\n }\n\n // handle cleared filters\n if (filters == {}) {\n return filteredEvents;\n }\n\n // handle title filter\n if (filters.title) {\n filteredEvents = filteredEvents.filter((event) => {\n return event.title.toLowerCase().includes(filters.title.toLowerCase());\n });\n }\n\n // handle location filter\n if (filters.location) {\n filteredEvents = filteredEvents.filter((event) => {\n return event?.extendedProps?.location\n .toLowerCase()\n .includes(filters.location.toLowerCase());\n });\n }\n\n // handle organizer filter\n if (filters.organizers.length) {\n const organizers =\n filters.organizers.map((it) => {\n if (it.customOption) {\n return it.organizers;\n }\n return it;\n }) ?? [];\n\n filteredEvents = filteredEvents.filter((event) => {\n const eventOrganizers = event?.extendedProps?.organizers.map((it) => {\n if (it.customOption) {\n return it.organizer;\n }\n return it;\n });\n return eventOrganizers.some((it) => organizers.includes(it));\n });\n }\n\n // handle tag filter\n if (filters.tags.length) {\n const tags =\n filters.tags.map((it) => {\n if (it.customOption) {\n return it.tags;\n }\n return it;\n }) ?? [];\n\n filteredEvents = filteredEvents.filter((event) => {\n const eventTags = event?.extendedProps?.hashtags.map((it) => {\n if (it.customOption) {\n return it.hashtags;\n }\n return it;\n });\n return eventTags.some((it) => tags.includes(it));\n });\n }\n\n return filteredEvents;\n};\n\nevents = filterEvents();\n\nconst CurrentView = () => {\n if (selectedView === \"month\") {\n return (\n <Widget\n src=\"buildhub.near/widget/events.MonthView\"\n loading=\"\"\n props={{\n currentDate,\n events,\n setSelectedView,\n }}\n />\n );\n }\n\n return (\n <Widget\n src=\"buildhub.near/widget/events.ListView\"\n loading=\"\"\n props={{\n currentDate,\n events,\n }}\n />\n );\n};\n\nconst Container = styled.div`\n background: var(--bg-1, #000000);\n`;\n\nreturn (\n <Container className=\"mb-3 mx-3\">\n <Widget\n src=\"buildhub.near/widget/components.modals.CreateEvent\"\n loading=\"\"\n props={{\n showModal: showCreateModal,\n toggleModal: toggleCreateModal,\n app,\n thing,\n }}\n />\n <Widget\n src=\"buildhub.near/widget/components.modals.FilterEvents\"\n loading=\"\"\n props={{\n showModal: showFilterModal,\n toggleModal: toggleFilterModal,\n filters: filters,\n setFilters: setFilters,\n }}\n />\n <Toolbar />\n <CurrentView />\n </Container>\n);\n" }, "components.modals.event.Form": { "": "const { Button } = VM.require(\"buildhub.near/widget/components\") || {\n Button: () => <></>,\n};\n\nconst bootstrapTheme = props.bootstrapTheme || \"dark\";\n\nconst MarkdownEditor = `\n html {\n background: #23242b;\n }\n\n * {\n border: none !important;\n }\n\n .rc-md-editor {\n background: #4f5055;\n border-top: 1px solid #4f5055 !important;\n border-radius: 8px;\n }\n\n .editor-container {\n background: #4f5055;\n }\n \n .drop-wrap {\n \n border-radius: 0.5rem !important;\n }\n\n .header-list {\n display: flex;\n align-items: center;\n }\n\n textarea {\n background: #23242b !important;\n color: #fff !important;\n\n font-family: sans-serif !important;\n font-size: 1rem;\n\n border: 1px solid #4f5055 !important;\n border-top: 0 !important;\n border-radius: 0 0 8px 8px;\n }\n\n .rc-md-navigation {\n background: #23242b !important;\n border: 1px solid #4f5055 !important;\n border-top: 0 !important;\n border-bottom: 0 !important;\n border-radius: 8px 8px 0 0;\n \n i {\n color: #cdd0d5;\n }\n }\n\n .editor-container {\n border-radius: 0 0 8px 8px;\n }\n\n .rc-md-editor .editor-container .sec-md .input {\n overflow-y: auto;\n padding: 8px !important;\n line-height: normal;\n border-radius: 0 0 8px 8px;\n }\n`;\n\nconst TextareaWrapper = styled.div`\n display: grid;\n vertical-align: top;\n align-items: center;\n position: relative;\n align-items: stretch;\n width: 100%;\n\n textarea {\n display: flex;\n align-items: center;\n transition: all 0.3s ease;\n }\n\n textarea::placeholder {\n padding-top: 4px;\n font-size: 20px;\n }\n\n textarea:focus::placeholder {\n font-size: inherit;\n padding-top: 0px;\n }\n\n &::after,\n textarea,\n iframe {\n width: 100%;\n min-width: 1em;\n height: unset;\n min-height: 3em;\n font: inherit;\n margin: 0;\n resize: none;\n background: none;\n appearance: none;\n border: 0px solid #eee;\n grid-area: 1 / 1;\n overflow: hidden;\n outline: none;\n }\n\n iframe {\n padding: 0;\n }\n\n textarea:focus,\n textarea:not(:empty) {\n border-bottom: 1px solid #eee;\n min-height: 5em;\n }\n\n &::after {\n content: attr(data-value) \" \";\n visibility: hidden;\n white-space: pre-wrap;\n }\n &.markdown-editor::after {\n padding-top: 66px;\n font-family: monospace;\n font-size: 14px;\n }\n`;\n\nconst getCurrentDate = (date, time) => {\n const currentDate = date && time ? new Date(`${date}T${time}`) : new Date();\n\n const year = currentDate.getFullYear();\n const month = (currentDate.getMonth() + 1).toString().padStart(2, \"0\"); // Months are 0-indexed\n const day = currentDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nconst getCurrentTime = (date, time) => {\n const currentDate = date && time ? new Date(`${date}T${time}`) : new Date();\n\n const hours = currentDate.getHours().toString().padStart(2, \"0\");\n const minutes = currentDate.getMinutes().toString().padStart(2, \"0\");\n\n return `${hours}:${minutes}`;\n};\n\nconst isoTime = (date, time) => {\n const temp = new Date(`${date} ${time}`);\n const now = temp.toISOString();\n\n return now.split(\"T\")[1];\n};\n\nconst isoDate = (date, time) => {\n const temp = new Date(`${date} ${time}`);\n const now = temp.toISOString();\n\n return now.split(\"T\")[0];\n};\n\nconst UUID = {\n generate: (template) => {\n if (typeof template !== \"string\") {\n template = \"xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx\";\n }\n return template.replace(/[xy]/g, (c) => {\n var r = (Math.random() * 16) | 0;\n var v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n },\n};\n\nconst [title, setTitle] = useState(\"\");\nconst [description, setDescription] = useState(\"\");\nconst [link, setLink] = useState(\"\");\nconst [organizers, setOrganizers] = useState([]);\nconst [startDate, setStartDate] = useState(getCurrentDate());\nconst [endDate, setEndDate] = useState(getCurrentDate());\nconst [startTime, setStartTime] = useState(getCurrentTime());\nconst [endTime, setEndTime] = useState(getCurrentTime());\nconst [location, setLocation] = useState(\"\");\nconst [hashtags, setHashtags] = useState([]);\nconst [customButtonSrc, setCustomButtonSrc] = useState(\"\");\n\nState.init({\n image: null,\n});\n\nconst app = props.app;\nconst thing = props.thing;\n\nconst onSubmit = () => {\n const thingId = UUID.generate(); // we could replace this with a normalized title\n // you mean just UUID();?\n\n Social.set(\n {\n [app]: {\n // we'll replace this with \"every\" or the specific app that the event should be visible in\n [thing]: {\n [thingId]: {\n \"\": JSON.stringify({\n title,\n description,\n url: link,\n start: `${isoDate(startDate, startTime)}T${isoTime(\n startDate,\n startTime,\n )}`, // we'll want this be available for filtering... we may want to store it outside the JSON\n // or we need an indexing solution\n // we fetch events and then apply filters after parsing them\n end: `${isoDate(endDate, endTime)}T${isoTime(endDate, endTime)}`,\n extendedProps: {\n organizers,\n location,\n hashtags, // this can be moved to metadata.tags, but must be object with keys, e.g { [hashtag]: \"\" }\n // this i'll leave up to you but we need them for filtering\n cover: state.image,\n customButtonSrc: customButtonSrc,\n },\n }),\n metadata: {\n name: title,\n description,\n image: state.image,\n backgroundImage: state.image,\n type: \"buildhub.near/type/event\",\n },\n },\n },\n },\n },\n {\n onCommit: () => props.toggleModal(),\n },\n );\n};\n\nconst onCoverChange = (target) => {\n State.update({ image: target });\n};\n\nreturn (\n <div data-bs-theme={bootstrapTheme}>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"title\">\n Title<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"title\"\n id=\"title\"\n type=\"text\"\n placeholder=\"Enter event name\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n </div>\n <div className=\"form-group mb-3\">\n <label>\n Event Description<span className=\"text-danger\">*</span>\n </label>\n <TextareaWrapper\n className=\"markdown-editor mb-3\"\n data-value={description || \"\"}\n key={memoizedKey || \"markdown-editor\"}\n >\n <Widget\n src=\"mob.near/widget/MarkdownEditorIframe\"\n props={{\n initialText: description,\n embedCss: props.customCSS || MarkdownEditor,\n onChange: (v) => {\n setDescription(v);\n },\n }}\n />\n </TextareaWrapper>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"link\">\n Event Link<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"link\"\n id=\"link\"\n type=\"text\"\n placeholder=\"Enter link\"\n value={link}\n onChange={(e) => setLink(e.target.value)}\n />\n </div>\n <div className=\"form-group mb-3 d-flex\" style={{ gap: 24 }}>\n <div className=\"form-group flex-grow-1\">\n <label htmlFor=\"start-date\">\n Start Date<span className=\"text-danger\">*</span>\n </label>\n <input\n id=\"start-date\"\n name=\"start-date\"\n type=\"date\"\n value={startDate}\n onChange={(e) => setStartDate(e.target.value)}\n />\n </div>\n <div className=\"form-group flex-grow-1\">\n <label htmlFor=\"end-date\">\n End Date<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"end-date\"\n id=\"end-date\"\n type=\"date\"\n value={endDate}\n onChange={(e) => setEndDate(e.target.value)}\n />\n </div>\n </div>\n <div className=\"form-group mb-3 d-flex\" style={{ gap: 24 }}>\n <div className=\"form-group flex-grow-1\">\n <label htmlFor=\"start-time\">\n Start Time<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"start-time\"\n id=\"start-time\"\n type=\"time\"\n value={startTime}\n onChange={(e) => setStartTime(e.target.value)}\n />\n </div>\n <div className=\"form-group flex-grow-1\">\n <label htmlFor=\"end-time\">\n End Time<span className=\"text-danger\">*</span>\n </label>\n <input\n id=\"end-time\"\n name=\"end-time\"\n type=\"time\"\n value={endTime}\n onChange={(e) => setEndTime(e.target.value)}\n />\n </div>\n </div>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"organizer\">\n Organizers<span className=\"text-danger\">*</span>\n </label>\n <Typeahead\n id=\"organizers\"\n onChange={(e) => setOrganizers(e)}\n selected={organizers}\n labelKey=\"organizer\"\n multiple\n emptyLabel=\"Start writing a new organizer\"\n placeholder=\"Enter organizers\"\n options={[]}\n allowNew\n />\n </div>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"location\">\n Location<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"location\"\n id=\"location\"\n type=\"text\"\n placeholder=\"Enter location\"\n value={location}\n onChange={(e) => setLocation(e.target.value)}\n />\n </div>\n <div className=\"form-group mb-3\" data-bs-theme={bootstrapTheme}>\n <label htmlFor=\"hashtags\">Hashtags</label>\n <Typeahead\n id=\"hashtags\"\n onChange={(e) => setHashtags(e)}\n selected={hashtags}\n multiple\n labelKey=\"hashtags\"\n emptyLabel=\"Start writing a new hashtag\"\n placeholder=\"Enter hashtags\"\n options={[\"build\", \"dao\", \"nft\", \"metaverse\", \"web3\"]}\n allowNew\n />\n </div>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"cover-image\">Cover Image</label>\n <Widget\n src=\"buildhub.near/widget/components.ImageUploader\"\n loading=\"\"\n props={{ image: state.image, onChange: onCoverChange }}\n />\n </div>\n <div className=\"form-group flex-grow-1\">\n <div className=\"d-flex align-items-center justify-content-between\">\n <label htmlFor=\"customButton\">Custom Button Souce</label>\n <a\n href=\"https://near.social/itexpert120-contra.near/widget/Button.Create\"\n target=\"_blank\"\n >\n <small>Create Button Here</small>\n </a>\n </div>\n <input\n id=\"customButton\"\n name=\"customButton\"\n type=\"text\"\n value={customButtonSrc}\n onChange={(e) => setCustomButtonSrc(e.target.value)}\n />\n </div>\n </div>\n <div className=\"d-flex justify-content-end\">\n <Button\n disabled={!title || !description || !link || !location || !organizers}\n variant=\"primary\"\n onClick={onSubmit}\n >\n Submit\n </Button>\n </div>\n </div>\n);\n" }, "home.Home": { "": "const { Hero } = VM.require(\"buildhub.near/widget/home.Hero\") || {\n Hero: () => <></>,\n};\nconst { Goals } = VM.require(\"buildhub.near/widget/home.Goals\") || {\n Goals: () => <></>,\n};\nconst { Join } = VM.require(\"buildhub.near/widget/home.Join\") || {\n Join: () => <></>,\n};\nconst { Purposes } = VM.require(\"buildhub.near/widget/home.Purposes\") || {\n Purposes: () => <></>,\n};\nconst { AboutUs } = VM.require(\"buildhub.near/widget/home.AboutUs\") || {\n AboutUs: () => <></>,\n};\nconst { Governance } = VM.require(\"buildhub.near/widget/home.Governance\") || {\n Governance: () => <></>,\n};\nconst { Footer } = VM.require(\"buildhub.near/widget/home.Footer\") || {\n Footer: () => <></>,\n};\n\nreturn {\n Hero,\n Goals,\n Join,\n Purposes,\n AboutUs,\n Governance,\n Footer,\n};\n" }, "events.ListView": { "": "const { Button, Hashtag } = VM.require(\"buildhub.near/widget/components\") || {\n Button: () => <></>,\n Hashtag: () => <></>,\n};\n\nconst events = props.events ?? [];\nconst currentDate = props.currentDate;\n\nif (!events || !currentDate) {\n return \"\";\n}\n\nconst currentMonthEvents = events.filter((event) => {\n const eventDate = new Date(event.start);\n return eventDate.getMonth() === currentDate.getMonth();\n});\n\nconst categorizedEvents = currentMonthEvents.reduce((result, event) => {\n const eventDate = new Date(event.start)\n .toLocaleDateString(\"en-us\", {\n day: \"numeric\",\n month: \"short\",\n })\n .split(\" \")\n .reverse()\n .join(\" \"); // Format date as a string\n result[eventDate] = result[eventDate] || [];\n result[eventDate].push(event);\n return result;\n}, {});\n\nconst EventsContainer = styled.div`\n display: flex;\n flex-direction: column;\n gap: 24px;\n`;\n\nconst StyledEvent = styled.div`\n border-radius: 16px;\n background: #23242b;\n display: flex;\n padding: 24px;\n flex-direction: column;\n justify-content: flex-end;\n align-items: flex-start;\n gap: 24px;\n\n color: var(--font-color, #fff);\n\n h4,\n p {\n margin: 0;\n }\n\n h4 {\n /* H4/Large */\n font-size: 18px;\n font-style: normal;\n font-weight: 500;\n line-height: 160%; /* 28.8px */\n }\n\n p {\n /* Body/16px */\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 170%; /* 27.2px */\n }\n\n .cover-image {\n img {\n width: 40px;\n height: 40px;\n object-fit: cover;\n border-radius: 8px;\n }\n }\n`;\n\nconst formatStartTime = (time) => {\n const date = new Date(time);\n const options = {\n hour: \"2-digit\",\n minute: \"2-digit\",\n timeZoneName: \"short\",\n };\n\n return date.toLocaleString(\"en-US\", options);\n};\n\nconst dateKeys = Object.keys(categorizedEvents);\n\nconst today = new Date();\n\nconst futureEvents = dateKeys.filter((date) => {\n return categorizedEvents[date].some((event) => {\n const eventStartDate = new Date(event.start);\n const eventEndDate = new Date(event.end);\n return eventStartDate >= today || eventEndDate > today;\n });\n});\n\nconst pastEvents = dateKeys.filter((date) => !futureEvents.includes(date));\n\nconst sortEvents = (events) => {\n return events.sort((a, b) => a.split(\" \")[0] + b.split(\" \"[0]));\n};\n\nfutureEvents.sort();\npastEvents.sort();\n\nconst EventGroup = ({ date }) => {\n const Container = styled.div`\n display: flex;\n flex-direction: row;\n gap: 32px;\n\n @media screen and (max-width: 768px) {\n flex-direction: column;\n gap: 24px;\n }\n `;\n\n return (\n <Container>\n <h3 className=\"flex-shrink-0 text-white\" style={{ minWidth: 65 }}>\n <div className=\"d-flex gap-3 align-items-center\">\n {date.split(\" \").map((it, i) => (\n <span\n style={{\n fontSize: i === 0 ? \"24px\" : \"16px\",\n color:\n i === 0\n ? \"var(--text-color, #fff)\"\n : \"var(--white-50, #CDD0D5)\",\n }}\n >\n {it}\n </span>\n ))}\n </div>\n </h3>\n <div className=\"w-100 d-flex flex-column gap-3\">\n {categorizedEvents[date].map((event, i) => {\n const hashtags =\n event?.extendedProps?.hashtags.map((it) => {\n if (it.customOption) {\n return it.hashtags;\n }\n return it;\n }) ?? [];\n const organizers =\n event?.extendedProps?.organizers.map((it) => {\n if (it.customOption) {\n return it.organizer;\n }\n return it;\n }) ?? [];\n\n const organizer = organizers[0];\n const organizerProfile = Social.getr(`${organizer}/profile`);\n\n const startTime = formatStartTime(event.start);\n\n return (\n <StyledEvent key={`event-${i}`}>\n <div className=\"d-flex align-items-center justify-content-between w-100\">\n <div className=\"d-flex align-items-center gap-2 flex-wrap\">\n {hashtags.map((tag) => (\n <Hashtag key={tag}>{tag}</Hashtag>\n ))}\n </div>\n <span>{startTime}</span>\n </div>\n <div className=\"d-flex gap-3\">\n <div className=\"cover-image\">\n <Widget\n src=\"mob.near/widget/Image\"\n props={{\n image: event.extendedProps.cover,\n fallbackUrl:\n \"https://ipfs.near.social/ipfs/bafkreibas66y6ewop5ix2n6mgybpjz6epg7opqvcplmm5jw4jlhdik5nhe\",\n }}\n />\n </div>\n <div>\n <h4>{event.title}</h4>\n <Markdown text={event.description} />\n </div>\n </div>\n <div className=\"d-flex align-items-center flex-wrap gap-3\">\n <span className=\"d-flex align-items-center gap-1\">\n <Widget\n src=\"mob.near/widget/Image\"\n loading=\"\"\n props={{\n image: organizerProfile.image,\n fallbackUrl:\n \"https://ipfs.near.social/ipfs/bafkreibas66y6ewop5ix2n6mgybpjz6epg7opqvcplmm5jw4jlhdik5nhe\",\n style: {\n width: 24,\n height: 24,\n borderRadius: 12,\n objectFit: \"cover\",\n },\n }}\n />\n {organizerProfile.name ?? organizers[0] ?? \"No name profile\"}\n </span>\n <span className=\"d-flex align-items-center gap-1\">\n <i className=\"bi bi-geo-alt\"></i>\n {event?.extendedProps?.location}\n </span>\n\n <span className=\"d-flex align-items-center gap-1\">\n <i className=\"bi bi-calendar\"></i>\n Last Date:{\" \"}\n {new Date(event.end).toLocaleString(\"en-us\", {\n day: \"numeric\",\n month: \"short\",\n })}\n </span>\n </div>\n <div className=\"d-flex align-items-center gap-3\">\n <Button\n noLink={true}\n href={`${event?.url}`}\n target=\"_blank\"\n variant=\"primary\"\n >\n Join Now\n </Button>\n {event.extendedProps.customButtonSrc && (\n <Widget\n src={event.extendedProps.customButtonSrc}\n loading=\"\"\n />\n )}\n </div>\n </StyledEvent>\n );\n })}\n </div>\n </Container>\n );\n};\n\nconst PastEvents = () => {\n return (\n <>\n {!pastEvents.length && (\n <p className=\"text-white\">No past events this month</p>\n )}\n {pastEvents.map((date, i) => (\n <EventGroup date={date} />\n ))}\n </>\n );\n};\n\nconst [showPastEvents, setShowPastEvents] = useState(false);\n\nreturn (\n <EventsContainer>\n <Button onClick={() => setShowPastEvents((prev) => !prev)}>\n {showPastEvents ? \"Hide\" : \"Show\"} Past Events\n </Button>\n {showPastEvents && <PastEvents />}\n {!futureEvents.length && (\n <p className=\"text-white\">No upcoming events this month</p>\n )}\n {futureEvents.map((date, i) => (\n <EventGroup date={date} />\n ))}\n </EventsContainer>\n);\n" }, "events.MonthView": { "": "const { Modal, Hashtag, Button } = VM.require(\n \"buildhub.near/widget/components\",\n) || {\n Modal: () => <></>,\n Hashtag: () => <></>,\n Button: () => <></>,\n};\n\nconst currentDate = props.currentDate || new Date();\nconst events = props.events || [];\n\nconst customCSS = `\n :root {\n --fc-page-bg-color: var(--bg-color, #000000);\n --fc-border-color: var(--stroke-color, rgba(255, 255, 255, 0.20));\n --fc-today-bg-color: #424451;\n }\n\n body {\n margin: 0;\n }\n\n html {\n background-color: var(--fc-page-bg-color);\n color: var(--text-color, #fff);\n font-family: sans-serif;\n }\n\n /* FC Header */\n .fc-col-header-cell {\n background: var(--bg-2, #23242B);\n .fc-col-header-cell-cushion {\n display: block;\n text-align: left;\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 170%; /* 27.2px */\n padding: 10px;\n }\n }\n\n /* FC Day */\n .fc-day-today {\n .fc-daygrid-day-frame {\n background: var(--fc-today-bg-color, #424451);\n }\n }\n\n .fc .fc-daygrid-event-harness {\n a {\n color: var(--text-color, #fff);\n }\n }\n\n .fc-day-other {\n .fc-daygrid-day-frame {\n background: var(--bg-1, #000000);\n }\n }\n\n .fc-daygrid-day-frame {\n padding: 10px;\n background: var(--bg-2, #23242B);\n }\n .fc .fc-daygrid-day-top {\n flex-direction: row;\n .fc-daygrid-day-number {\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 170%; /* 27.2px */\n }\n }\n`;\n\nconst embedCss = props.embedCss || customCSS;\n\nconst code = `\n<script src='https://cdn.jsdelivr.net/npm/fullcalendar/index.global.js'></script>\n<!-- iframe-resizer -->\n<!-- <script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.6/iframeResizer.contentWindow.js\"></script> -->\n\n<style>\n ${embedCss}\n</style>\n\n<div id=\"calendar\"></div>\n\n<script>\n document.addEventListener('DOMContentLoaded', function() {\n var calendarEl = document.getElementById('calendar');\n var calendar = new FullCalendar.Calendar(calendarEl, {\n initialView: 'dayGridMonth',\n headerToolbar: false,\n events: ${JSON.stringify(events)},\n eventClick: function(info) {\n info.jsEvent.preventDefault(); // don't let the browser navigate\n // Post the event details to the parent window\n window.parent.postMessage(JSON.stringify({ event: info.event}), '*');\n },\n });\n calendar.render();\n calendar.gotoDate(new Date(${currentDate.getTime()}));\n });\n</script>\n`;\n\nconst [data, setData] = useState(null);\nconst [showModal, setShowModal] = useState(false);\n\nconst toggleModal = () => {\n setShowModal((prev) => !prev);\n};\n\nconst organizers =\n (data?.extendedProps?.organizers || []).map((it) => {\n if (it.customOption) {\n return it.organizer;\n }\n return it;\n }) ?? [];\n\nconst hashtags =\n (data?.extendedProps?.hashtags || []).map((it) => {\n if (it.customOption) {\n return it.hashtags;\n }\n return it;\n }) ?? [];\n\nreturn (\n <>\n <iframe\n srcDoc={code}\n onMessage={(data) => {\n const dataObj = JSON.parse(data);\n setData(dataObj.event);\n toggleModal();\n }}\n style={{\n width: \"100%\",\n height: \"100vh\",\n }}\n />\n {data && (\n <Modal open={showModal} onOpenChange={toggleModal} title={data.title}>\n <div style={{ maxWidth: 600 }}>\n <div className=\"mb-3 d-flex align-items-center justify-content-between flex-wrap\">\n <span>\n <i className=\"bi bi-calendar\"></i> Start Date Time:{\" \"}\n {new Date(data.start).toLocaleDateString(\"en-us\", {\n hour: \"2-digit\",\n minute: \"numeric\",\n })}\n </span>\n <span>\n <i className=\"bi bi-calendar\"></i> End Date Time:{\" \"}\n {new Date(data.end).toLocaleDateString(\"en-us\", {\n hour: \"2-digit\",\n minute: \"numeric\",\n })}\n </span>\n </div>\n {data.extendedProps.description && (\n <div className=\"mb-3\">\n <h5 style={{ fontSize: 12, fontWeight: 700, marginBottom: 8 }}>\n DESCRIPTION\n </h5>\n <p>{data.extendedProps.description}</p>\n </div>\n )}\n {organizers.length > 0 && (\n <div className=\"mb-3\">\n <h5 style={{ fontSize: 12, fontWeight: 700, marginBottom: 8 }}>\n ORGANIZERS\n </h5>\n {organizers.map((organizer) => {\n const organizerProfile = Social.getr(`${organizer}/profile`);\n return (\n <span className=\"d-flex align-items-center gap-1\">\n <Widget\n src=\"mob.near/widget/Image\"\n loading=\"\"\n props={{\n image: organizerProfile.image,\n fallbackUrl:\n \"https://ipfs.near.social/ipfs/bafkreibas66y6ewop5ix2n6mgybpjz6epg7opqvcplmm5jw4jlhdik5nhe\",\n style: {\n width: 24,\n height: 24,\n borderRadius: 12,\n objectFit: \"cover\",\n },\n }}\n />\n {organizerProfile.name ??\n organizers[0] ??\n \"No name profile\"}\n </span>\n );\n })}\n </div>\n )}\n {hashtags.length > 0 && (\n <div className=\"mb-3\">\n <h5 style={{ fontSize: 12, fontWeight: 700, marginBottom: 8 }}>\n HASHTAGS\n </h5>\n <div className=\"d-flex align-items-center gap-2 flex-wrap\">\n {hashtags.map((tag) => (\n <Hashtag key={tag}>{tag}</Hashtag>\n ))}\n </div>\n </div>\n )}\n {data.extendedProps.location && (\n <span className=\"d-flex align-items-center gap-1 mb-3\">\n <i className=\"bi bi-geo-alt\"></i>\n {data?.extendedProps?.location}\n </span>\n )}\n </div>\n <div className=\"d-flex align-items-center gap-3\">\n <Button\n noLink={true}\n href={`${data?.url}`}\n target=\"_blank\"\n variant=\"primary\"\n >\n Join Now\n </Button>\n {data.extendedProps.customButtonSrc && (\n <Widget src={data.extendedProps.customButtonSrc} loading=\"\" />\n )}\n </div>\n </Modal>\n )}\n </>\n);\n" } } } } }

Transaction Execution Plan

Convert Transaction To Receipt
Gas Burned:
2 Tgas
Tokens Burned:
0.00025 
Receipt:
Predecessor ID:
Receiver ID:
Gas Burned:
14 Tgas
Tokens Burned:
0.00144 
Called method: 'set' in contract: social.near
Arguments:
{ "data": { "buildhub.near": { "widget": { "events.Calendar": { "": "const { Button } = VM.require(\"buildhub.near/widget/components\") || {\n Button: () => <></>,\n};\n\nconst { fetchThings } = VM.require(\n \"buildhub.near/widget/lib.everything-sdk\"\n) || {\n fetchThings: () => {},\n};\n\nconst StyledToolbar = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n border: 1px solid var(--stroke-color, rgba(255, 255, 255, 0.2));\n padding: 16px 24px;\n margin-bottom: 24px;\n\n background: var(--bg-1, #000000);\n\n color: var(--text-color, #fff);\n font-size: 18px;\n\n .section {\n display: flex;\n align-items: center;\n flex-basis: 0;\n flex-grow: 1;\n }\n\n .date-changer {\n all: unset;\n cursor: pointer;\n }\n\n @media screen and (max-width: 768px) {\n flex-direction: column;\n gap: 1rem;\n }\n`;\n\n// implement event fetching and filtering\n\nconst [selectedView, setSelectedView] = useState(\"month\");\nconst [currentDate, setCurrentDate] = useState(new Date());\n\nconst [showCreateModal, setShowCreateModal] = useState(false);\nconst toggleCreateModal = () => setShowCreateModal(!showCreateModal);\n\nconst [showFilterModal, setShowFilterModal] = useState(false);\nconst toggleFilterModal = () => setShowFilterModal(!showFilterModal);\n\nconst [filters, setFilters] = useState({});\n\nconst dateString = currentDate.toLocaleString(\"en-us\", {\n month: \"long\",\n year: \"numeric\",\n});\n\nconst handleMonthChange = (change) => {\n const date = currentDate;\n date.setMonth(date.getMonth() + change);\n setCurrentDate(date);\n};\n\nconst Toolbar = () => {\n return (\n <StyledToolbar>\n <div className=\"section gap-3\">\n <span>{dateString}</span>\n <button className=\"date-changer\" onClick={() => handleMonthChange(-1)}>\n <i className=\"bi bi-chevron-left\"></i>\n </button>\n <button className=\"date-changer\" onClick={() => handleMonthChange(1)}>\n <i className=\"bi bi-chevron-right\"></i>\n </button>\n </div>\n <div className=\"section gap-1 justify-content-center\">\n <Button\n variant={selectedView === \"month\" ? \"secondary\" : \"outline\"}\n onClick={() => setSelectedView(\"month\")}\n >\n Month\n </Button>\n <Button\n variant={selectedView === \"list\" ? \"secondary\" : \"outline\"}\n onClick={() => setSelectedView(\"list\")}\n >\n List\n </Button>\n </div>\n <div className=\"section justify-content-end\" style={{ gap: 10 }}>\n <Button variant=\"outline\" onClick={() => setShowFilterModal(true)}>\n Filter By\n </Button>\n {context.accountId && (\n <Button variant=\"primary\" onClick={() => setShowCreateModal(true)}>\n Add Event\n </Button>\n )}\n </div>\n </StyledToolbar>\n );\n};\n\nconst app = props.app ?? \"every\";\nconst thing = props.thing ?? \"event\";\nconst events = fetchThings(app, thing);\n\nconst filterEvents = () => {\n let filteredEvents = events;\n\n // handle date from filter\n if (filters.from) {\n filteredEvents = filteredEvents.filter((event) => {\n return new Date(event.start) >= new Date(filters.from);\n });\n }\n\n // handle date to filter\n if (filters.to) {\n filteredEvents = filteredEvents.filter((event) => {\n return new Date(event.start) <= new Date(filters.to);\n });\n }\n\n // handle cleared filters\n if (filters == {}) {\n return filteredEvents;\n }\n\n // handle title filter\n if (filters.title) {\n filteredEvents = filteredEvents.filter((event) => {\n return event.title.toLowerCase().includes(filters.title.toLowerCase());\n });\n }\n\n // handle location filter\n if (filters.location) {\n filteredEvents = filteredEvents.filter((event) => {\n return event?.extendedProps?.location\n .toLowerCase()\n .includes(filters.location.toLowerCase());\n });\n }\n\n // handle organizer filter\n if (filters.organizers.length) {\n const organizers =\n filters.organizers.map((it) => {\n if (it.customOption) {\n return it.organizers;\n }\n return it;\n }) ?? [];\n\n filteredEvents = filteredEvents.filter((event) => {\n const eventOrganizers = event?.extendedProps?.organizers.map((it) => {\n if (it.customOption) {\n return it.organizer;\n }\n return it;\n });\n return eventOrganizers.some((it) => organizers.includes(it));\n });\n }\n\n // handle tag filter\n if (filters.tags.length) {\n const tags =\n filters.tags.map((it) => {\n if (it.customOption) {\n return it.tags;\n }\n return it;\n }) ?? [];\n\n filteredEvents = filteredEvents.filter((event) => {\n const eventTags = event?.extendedProps?.hashtags.map((it) => {\n if (it.customOption) {\n return it.hashtags;\n }\n return it;\n });\n return eventTags.some((it) => tags.includes(it));\n });\n }\n\n return filteredEvents;\n};\n\nevents = filterEvents();\n\nconst CurrentView = () => {\n if (selectedView === \"month\") {\n return (\n <Widget\n src=\"buildhub.near/widget/events.MonthView\"\n loading=\"\"\n props={{\n currentDate,\n events,\n setSelectedView,\n }}\n />\n );\n }\n\n return (\n <Widget\n src=\"buildhub.near/widget/events.ListView\"\n loading=\"\"\n props={{\n currentDate,\n events,\n }}\n />\n );\n};\n\nconst Container = styled.div`\n background: var(--bg-1, #000000);\n`;\n\nreturn (\n <Container className=\"mb-3 mx-3\">\n <Widget\n src=\"buildhub.near/widget/components.modals.CreateEvent\"\n loading=\"\"\n props={{\n showModal: showCreateModal,\n toggleModal: toggleCreateModal,\n app,\n thing,\n }}\n />\n <Widget\n src=\"buildhub.near/widget/components.modals.FilterEvents\"\n loading=\"\"\n props={{\n showModal: showFilterModal,\n toggleModal: toggleFilterModal,\n filters: filters,\n setFilters: setFilters,\n }}\n />\n <Toolbar />\n <CurrentView />\n </Container>\n);\n" }, "components.modals.event.Form": { "": "const { Button } = VM.require(\"buildhub.near/widget/components\") || {\n Button: () => <></>,\n};\n\nconst bootstrapTheme = props.bootstrapTheme || \"dark\";\n\nconst MarkdownEditor = `\n html {\n background: #23242b;\n }\n\n * {\n border: none !important;\n }\n\n .rc-md-editor {\n background: #4f5055;\n border-top: 1px solid #4f5055 !important;\n border-radius: 8px;\n }\n\n .editor-container {\n background: #4f5055;\n }\n \n .drop-wrap {\n \n border-radius: 0.5rem !important;\n }\n\n .header-list {\n display: flex;\n align-items: center;\n }\n\n textarea {\n background: #23242b !important;\n color: #fff !important;\n\n font-family: sans-serif !important;\n font-size: 1rem;\n\n border: 1px solid #4f5055 !important;\n border-top: 0 !important;\n border-radius: 0 0 8px 8px;\n }\n\n .rc-md-navigation {\n background: #23242b !important;\n border: 1px solid #4f5055 !important;\n border-top: 0 !important;\n border-bottom: 0 !important;\n border-radius: 8px 8px 0 0;\n \n i {\n color: #cdd0d5;\n }\n }\n\n .editor-container {\n border-radius: 0 0 8px 8px;\n }\n\n .rc-md-editor .editor-container .sec-md .input {\n overflow-y: auto;\n padding: 8px !important;\n line-height: normal;\n border-radius: 0 0 8px 8px;\n }\n`;\n\nconst TextareaWrapper = styled.div`\n display: grid;\n vertical-align: top;\n align-items: center;\n position: relative;\n align-items: stretch;\n width: 100%;\n\n textarea {\n display: flex;\n align-items: center;\n transition: all 0.3s ease;\n }\n\n textarea::placeholder {\n padding-top: 4px;\n font-size: 20px;\n }\n\n textarea:focus::placeholder {\n font-size: inherit;\n padding-top: 0px;\n }\n\n &::after,\n textarea,\n iframe {\n width: 100%;\n min-width: 1em;\n height: unset;\n min-height: 3em;\n font: inherit;\n margin: 0;\n resize: none;\n background: none;\n appearance: none;\n border: 0px solid #eee;\n grid-area: 1 / 1;\n overflow: hidden;\n outline: none;\n }\n\n iframe {\n padding: 0;\n }\n\n textarea:focus,\n textarea:not(:empty) {\n border-bottom: 1px solid #eee;\n min-height: 5em;\n }\n\n &::after {\n content: attr(data-value) \" \";\n visibility: hidden;\n white-space: pre-wrap;\n }\n &.markdown-editor::after {\n padding-top: 66px;\n font-family: monospace;\n font-size: 14px;\n }\n`;\n\nconst getCurrentDate = (date, time) => {\n const currentDate = date && time ? new Date(`${date}T${time}`) : new Date();\n\n const year = currentDate.getFullYear();\n const month = (currentDate.getMonth() + 1).toString().padStart(2, \"0\"); // Months are 0-indexed\n const day = currentDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nconst getCurrentTime = (date, time) => {\n const currentDate = date && time ? new Date(`${date}T${time}`) : new Date();\n\n const hours = currentDate.getHours().toString().padStart(2, \"0\");\n const minutes = currentDate.getMinutes().toString().padStart(2, \"0\");\n\n return `${hours}:${minutes}`;\n};\n\nconst isoTime = (date, time) => {\n const temp = new Date(`${date} ${time}`);\n const now = temp.toISOString();\n\n return now.split(\"T\")[1];\n};\n\nconst isoDate = (date, time) => {\n const temp = new Date(`${date} ${time}`);\n const now = temp.toISOString();\n\n return now.split(\"T\")[0];\n};\n\nconst UUID = {\n generate: (template) => {\n if (typeof template !== \"string\") {\n template = \"xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx\";\n }\n return template.replace(/[xy]/g, (c) => {\n var r = (Math.random() * 16) | 0;\n var v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n },\n};\n\nconst [title, setTitle] = useState(\"\");\nconst [description, setDescription] = useState(\"\");\nconst [link, setLink] = useState(\"\");\nconst [organizers, setOrganizers] = useState([]);\nconst [startDate, setStartDate] = useState(getCurrentDate());\nconst [endDate, setEndDate] = useState(getCurrentDate());\nconst [startTime, setStartTime] = useState(getCurrentTime());\nconst [endTime, setEndTime] = useState(getCurrentTime());\nconst [location, setLocation] = useState(\"\");\nconst [hashtags, setHashtags] = useState([]);\nconst [customButtonSrc, setCustomButtonSrc] = useState(\"\");\n\nState.init({\n image: null,\n});\n\nconst app = props.app;\nconst thing = props.thing;\n\nconst onSubmit = () => {\n const thingId = UUID.generate(); // we could replace this with a normalized title\n // you mean just UUID();?\n\n Social.set(\n {\n [app]: {\n // we'll replace this with \"every\" or the specific app that the event should be visible in\n [thing]: {\n [thingId]: {\n \"\": JSON.stringify({\n title,\n description,\n url: link,\n start: `${isoDate(startDate, startTime)}T${isoTime(\n startDate,\n startTime,\n )}`, // we'll want this be available for filtering... we may want to store it outside the JSON\n // or we need an indexing solution\n // we fetch events and then apply filters after parsing them\n end: `${isoDate(endDate, endTime)}T${isoTime(endDate, endTime)}`,\n extendedProps: {\n organizers,\n location,\n hashtags, // this can be moved to metadata.tags, but must be object with keys, e.g { [hashtag]: \"\" }\n // this i'll leave up to you but we need them for filtering\n cover: state.image,\n customButtonSrc: customButtonSrc,\n },\n }),\n metadata: {\n name: title,\n description,\n image: state.image,\n backgroundImage: state.image,\n type: \"buildhub.near/type/event\",\n },\n },\n },\n },\n },\n {\n onCommit: () => props.toggleModal(),\n },\n );\n};\n\nconst onCoverChange = (target) => {\n State.update({ image: target });\n};\n\nreturn (\n <div data-bs-theme={bootstrapTheme}>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"title\">\n Title<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"title\"\n id=\"title\"\n type=\"text\"\n placeholder=\"Enter event name\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n </div>\n <div className=\"form-group mb-3\">\n <label>\n Event Description<span className=\"text-danger\">*</span>\n </label>\n <TextareaWrapper\n className=\"markdown-editor mb-3\"\n data-value={description || \"\"}\n key={memoizedKey || \"markdown-editor\"}\n >\n <Widget\n src=\"mob.near/widget/MarkdownEditorIframe\"\n props={{\n initialText: description,\n embedCss: props.customCSS || MarkdownEditor,\n onChange: (v) => {\n setDescription(v);\n },\n }}\n />\n </TextareaWrapper>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"link\">\n Event Link<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"link\"\n id=\"link\"\n type=\"text\"\n placeholder=\"Enter link\"\n value={link}\n onChange={(e) => setLink(e.target.value)}\n />\n </div>\n <div className=\"form-group mb-3 d-flex\" style={{ gap: 24 }}>\n <div className=\"form-group flex-grow-1\">\n <label htmlFor=\"start-date\">\n Start Date<span className=\"text-danger\">*</span>\n </label>\n <input\n id=\"start-date\"\n name=\"start-date\"\n type=\"date\"\n value={startDate}\n onChange={(e) => setStartDate(e.target.value)}\n />\n </div>\n <div className=\"form-group flex-grow-1\">\n <label htmlFor=\"end-date\">\n End Date<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"end-date\"\n id=\"end-date\"\n type=\"date\"\n value={endDate}\n onChange={(e) => setEndDate(e.target.value)}\n />\n </div>\n </div>\n <div className=\"form-group mb-3 d-flex\" style={{ gap: 24 }}>\n <div className=\"form-group flex-grow-1\">\n <label htmlFor=\"start-time\">\n Start Time<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"start-time\"\n id=\"start-time\"\n type=\"time\"\n value={startTime}\n onChange={(e) => setStartTime(e.target.value)}\n />\n </div>\n <div className=\"form-group flex-grow-1\">\n <label htmlFor=\"end-time\">\n End Time<span className=\"text-danger\">*</span>\n </label>\n <input\n id=\"end-time\"\n name=\"end-time\"\n type=\"time\"\n value={endTime}\n onChange={(e) => setEndTime(e.target.value)}\n />\n </div>\n </div>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"organizer\">\n Organizers<span className=\"text-danger\">*</span>\n </label>\n <Typeahead\n id=\"organizers\"\n onChange={(e) => setOrganizers(e)}\n selected={organizers}\n labelKey=\"organizer\"\n multiple\n emptyLabel=\"Start writing a new organizer\"\n placeholder=\"Enter organizers\"\n options={[]}\n allowNew\n />\n </div>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"location\">\n Location<span className=\"text-danger\">*</span>\n </label>\n <input\n name=\"location\"\n id=\"location\"\n type=\"text\"\n placeholder=\"Enter location\"\n value={location}\n onChange={(e) => setLocation(e.target.value)}\n />\n </div>\n <div className=\"form-group mb-3\" data-bs-theme={bootstrapTheme}>\n <label htmlFor=\"hashtags\">Hashtags</label>\n <Typeahead\n id=\"hashtags\"\n onChange={(e) => setHashtags(e)}\n selected={hashtags}\n multiple\n labelKey=\"hashtags\"\n emptyLabel=\"Start writing a new hashtag\"\n placeholder=\"Enter hashtags\"\n options={[\"build\", \"dao\", \"nft\", \"metaverse\", \"web3\"]}\n allowNew\n />\n </div>\n <div className=\"form-group mb-3\">\n <label htmlFor=\"cover-image\">Cover Image</label>\n <Widget\n src=\"buildhub.near/widget/components.ImageUploader\"\n loading=\"\"\n props={{ image: state.image, onChange: onCoverChange }}\n />\n </div>\n <div className=\"form-group flex-grow-1\">\n <div className=\"d-flex align-items-center justify-content-between\">\n <label htmlFor=\"customButton\">Custom Button Souce</label>\n <a\n href=\"https://near.social/itexpert120-contra.near/widget/Button.Create\"\n target=\"_blank\"\n >\n <small>Create Button Here</small>\n </a>\n </div>\n <input\n id=\"customButton\"\n name=\"customButton\"\n type=\"text\"\n value={customButtonSrc}\n onChange={(e) => setCustomButtonSrc(e.target.value)}\n />\n </div>\n </div>\n <div className=\"d-flex justify-content-end\">\n <Button\n disabled={!title || !description || !link || !location || !organizers}\n variant=\"primary\"\n onClick={onSubmit}\n >\n Submit\n </Button>\n </div>\n </div>\n);\n" }, "home.Home": { "": "const { Hero } = VM.require(\"buildhub.near/widget/home.Hero\") || {\n Hero: () => <></>,\n};\nconst { Goals } = VM.require(\"buildhub.near/widget/home.Goals\") || {\n Goals: () => <></>,\n};\nconst { Join } = VM.require(\"buildhub.near/widget/home.Join\") || {\n Join: () => <></>,\n};\nconst { Purposes } = VM.require(\"buildhub.near/widget/home.Purposes\") || {\n Purposes: () => <></>,\n};\nconst { AboutUs } = VM.require(\"buildhub.near/widget/home.AboutUs\") || {\n AboutUs: () => <></>,\n};\nconst { Governance } = VM.require(\"buildhub.near/widget/home.Governance\") || {\n Governance: () => <></>,\n};\nconst { Footer } = VM.require(\"buildhub.near/widget/home.Footer\") || {\n Footer: () => <></>,\n};\n\nreturn {\n Hero,\n Goals,\n Join,\n Purposes,\n AboutUs,\n Governance,\n Footer,\n};\n" }, "events.ListView": { "": "const { Button, Hashtag } = VM.require(\"buildhub.near/widget/components\") || {\n Button: () => <></>,\n Hashtag: () => <></>,\n};\n\nconst events = props.events ?? [];\nconst currentDate = props.currentDate;\n\nif (!events || !currentDate) {\n return \"\";\n}\n\nconst currentMonthEvents = events.filter((event) => {\n const eventDate = new Date(event.start);\n return eventDate.getMonth() === currentDate.getMonth();\n});\n\nconst categorizedEvents = currentMonthEvents.reduce((result, event) => {\n const eventDate = new Date(event.start)\n .toLocaleDateString(\"en-us\", {\n day: \"numeric\",\n month: \"short\",\n })\n .split(\" \")\n .reverse()\n .join(\" \"); // Format date as a string\n result[eventDate] = result[eventDate] || [];\n result[eventDate].push(event);\n return result;\n}, {});\n\nconst EventsContainer = styled.div`\n display: flex;\n flex-direction: column;\n gap: 24px;\n`;\n\nconst StyledEvent = styled.div`\n border-radius: 16px;\n background: #23242b;\n display: flex;\n padding: 24px;\n flex-direction: column;\n justify-content: flex-end;\n align-items: flex-start;\n gap: 24px;\n\n color: var(--font-color, #fff);\n\n h4,\n p {\n margin: 0;\n }\n\n h4 {\n /* H4/Large */\n font-size: 18px;\n font-style: normal;\n font-weight: 500;\n line-height: 160%; /* 28.8px */\n }\n\n p {\n /* Body/16px */\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 170%; /* 27.2px */\n }\n\n .cover-image {\n img {\n width: 40px;\n height: 40px;\n object-fit: cover;\n border-radius: 8px;\n }\n }\n`;\n\nconst formatStartTime = (time) => {\n const date = new Date(time);\n const options = {\n hour: \"2-digit\",\n minute: \"2-digit\",\n timeZoneName: \"short\",\n };\n\n return date.toLocaleString(\"en-US\", options);\n};\n\nconst dateKeys = Object.keys(categorizedEvents);\n\nconst today = new Date();\n\nconst futureEvents = dateKeys.filter((date) => {\n return categorizedEvents[date].some((event) => {\n const eventStartDate = new Date(event.start);\n const eventEndDate = new Date(event.end);\n return eventStartDate >= today || eventEndDate > today;\n });\n});\n\nconst pastEvents = dateKeys.filter((date) => !futureEvents.includes(date));\n\nconst sortEvents = (events) => {\n return events.sort((a, b) => a.split(\" \")[0] + b.split(\" \"[0]));\n};\n\nfutureEvents.sort();\npastEvents.sort();\n\nconst EventGroup = ({ date }) => {\n const Container = styled.div`\n display: flex;\n flex-direction: row;\n gap: 32px;\n\n @media screen and (max-width: 768px) {\n flex-direction: column;\n gap: 24px;\n }\n `;\n\n return (\n <Container>\n <h3 className=\"flex-shrink-0 text-white\" style={{ minWidth: 65 }}>\n <div className=\"d-flex gap-3 align-items-center\">\n {date.split(\" \").map((it, i) => (\n <span\n style={{\n fontSize: i === 0 ? \"24px\" : \"16px\",\n color:\n i === 0\n ? \"var(--text-color, #fff)\"\n : \"var(--white-50, #CDD0D5)\",\n }}\n >\n {it}\n </span>\n ))}\n </div>\n </h3>\n <div className=\"w-100 d-flex flex-column gap-3\">\n {categorizedEvents[date].map((event, i) => {\n const hashtags =\n event?.extendedProps?.hashtags.map((it) => {\n if (it.customOption) {\n return it.hashtags;\n }\n return it;\n }) ?? [];\n const organizers =\n event?.extendedProps?.organizers.map((it) => {\n if (it.customOption) {\n return it.organizer;\n }\n return it;\n }) ?? [];\n\n const organizer = organizers[0];\n const organizerProfile = Social.getr(`${organizer}/profile`);\n\n const startTime = formatStartTime(event.start);\n\n return (\n <StyledEvent key={`event-${i}`}>\n <div className=\"d-flex align-items-center justify-content-between w-100\">\n <div className=\"d-flex align-items-center gap-2 flex-wrap\">\n {hashtags.map((tag) => (\n <Hashtag key={tag}>{tag}</Hashtag>\n ))}\n </div>\n <span>{startTime}</span>\n </div>\n <div className=\"d-flex gap-3\">\n <div className=\"cover-image\">\n <Widget\n src=\"mob.near/widget/Image\"\n props={{\n image: event.extendedProps.cover,\n fallbackUrl:\n \"https://ipfs.near.social/ipfs/bafkreibas66y6ewop5ix2n6mgybpjz6epg7opqvcplmm5jw4jlhdik5nhe\",\n }}\n />\n </div>\n <div>\n <h4>{event.title}</h4>\n <Markdown text={event.description} />\n </div>\n </div>\n <div className=\"d-flex align-items-center flex-wrap gap-3\">\n <span className=\"d-flex align-items-center gap-1\">\n <Widget\n src=\"mob.near/widget/Image\"\n loading=\"\"\n props={{\n image: organizerProfile.image,\n fallbackUrl:\n \"https://ipfs.near.social/ipfs/bafkreibas66y6ewop5ix2n6mgybpjz6epg7opqvcplmm5jw4jlhdik5nhe\",\n style: {\n width: 24,\n height: 24,\n borderRadius: 12,\n objectFit: \"cover\",\n },\n }}\n />\n {organizerProfile.name ?? organizers[0] ?? \"No name profile\"}\n </span>\n <span className=\"d-flex align-items-center gap-1\">\n <i className=\"bi bi-geo-alt\"></i>\n {event?.extendedProps?.location}\n </span>\n\n <span className=\"d-flex align-items-center gap-1\">\n <i className=\"bi bi-calendar\"></i>\n Last Date:{\" \"}\n {new Date(event.end).toLocaleString(\"en-us\", {\n day: \"numeric\",\n month: \"short\",\n })}\n </span>\n </div>\n <div className=\"d-flex align-items-center gap-3\">\n <Button\n noLink={true}\n href={`${event?.url}`}\n target=\"_blank\"\n variant=\"primary\"\n >\n Join Now\n </Button>\n {event.extendedProps.customButtonSrc && (\n <Widget\n src={event.extendedProps.customButtonSrc}\n loading=\"\"\n />\n )}\n </div>\n </StyledEvent>\n );\n })}\n </div>\n </Container>\n );\n};\n\nconst PastEvents = () => {\n return (\n <>\n {!pastEvents.length && (\n <p className=\"text-white\">No past events this month</p>\n )}\n {pastEvents.map((date, i) => (\n <EventGroup date={date} />\n ))}\n </>\n );\n};\n\nconst [showPastEvents, setShowPastEvents] = useState(false);\n\nreturn (\n <EventsContainer>\n <Button onClick={() => setShowPastEvents((prev) => !prev)}>\n {showPastEvents ? \"Hide\" : \"Show\"} Past Events\n </Button>\n {showPastEvents && <PastEvents />}\n {!futureEvents.length && (\n <p className=\"text-white\">No upcoming events this month</p>\n )}\n {futureEvents.map((date, i) => (\n <EventGroup date={date} />\n ))}\n </EventsContainer>\n);\n" }, "events.MonthView": { "": "const { Modal, Hashtag, Button } = VM.require(\n \"buildhub.near/widget/components\",\n) || {\n Modal: () => <></>,\n Hashtag: () => <></>,\n Button: () => <></>,\n};\n\nconst currentDate = props.currentDate || new Date();\nconst events = props.events || [];\n\nconst customCSS = `\n :root {\n --fc-page-bg-color: var(--bg-color, #000000);\n --fc-border-color: var(--stroke-color, rgba(255, 255, 255, 0.20));\n --fc-today-bg-color: #424451;\n }\n\n body {\n margin: 0;\n }\n\n html {\n background-color: var(--fc-page-bg-color);\n color: var(--text-color, #fff);\n font-family: sans-serif;\n }\n\n /* FC Header */\n .fc-col-header-cell {\n background: var(--bg-2, #23242B);\n .fc-col-header-cell-cushion {\n display: block;\n text-align: left;\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 170%; /* 27.2px */\n padding: 10px;\n }\n }\n\n /* FC Day */\n .fc-day-today {\n .fc-daygrid-day-frame {\n background: var(--fc-today-bg-color, #424451);\n }\n }\n\n .fc .fc-daygrid-event-harness {\n a {\n color: var(--text-color, #fff);\n }\n }\n\n .fc-day-other {\n .fc-daygrid-day-frame {\n background: var(--bg-1, #000000);\n }\n }\n\n .fc-daygrid-day-frame {\n padding: 10px;\n background: var(--bg-2, #23242B);\n }\n .fc .fc-daygrid-day-top {\n flex-direction: row;\n .fc-daygrid-day-number {\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 170%; /* 27.2px */\n }\n }\n`;\n\nconst embedCss = props.embedCss || customCSS;\n\nconst code = `\n<script src='https://cdn.jsdelivr.net/npm/fullcalendar/index.global.js'></script>\n<!-- iframe-resizer -->\n<!-- <script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.6/iframeResizer.contentWindow.js\"></script> -->\n\n<style>\n ${embedCss}\n</style>\n\n<div id=\"calendar\"></div>\n\n<script>\n document.addEventListener('DOMContentLoaded', function() {\n var calendarEl = document.getElementById('calendar');\n var calendar = new FullCalendar.Calendar(calendarEl, {\n initialView: 'dayGridMonth',\n headerToolbar: false,\n events: ${JSON.stringify(events)},\n eventClick: function(info) {\n info.jsEvent.preventDefault(); // don't let the browser navigate\n // Post the event details to the parent window\n window.parent.postMessage(JSON.stringify({ event: info.event}), '*');\n },\n });\n calendar.render();\n calendar.gotoDate(new Date(${currentDate.getTime()}));\n });\n</script>\n`;\n\nconst [data, setData] = useState(null);\nconst [showModal, setShowModal] = useState(false);\n\nconst toggleModal = () => {\n setShowModal((prev) => !prev);\n};\n\nconst organizers =\n (data?.extendedProps?.organizers || []).map((it) => {\n if (it.customOption) {\n return it.organizer;\n }\n return it;\n }) ?? [];\n\nconst hashtags =\n (data?.extendedProps?.hashtags || []).map((it) => {\n if (it.customOption) {\n return it.hashtags;\n }\n return it;\n }) ?? [];\n\nreturn (\n <>\n <iframe\n srcDoc={code}\n onMessage={(data) => {\n const dataObj = JSON.parse(data);\n setData(dataObj.event);\n toggleModal();\n }}\n style={{\n width: \"100%\",\n height: \"100vh\",\n }}\n />\n {data && (\n <Modal open={showModal} onOpenChange={toggleModal} title={data.title}>\n <div style={{ maxWidth: 600 }}>\n <div className=\"mb-3 d-flex align-items-center justify-content-between flex-wrap\">\n <span>\n <i className=\"bi bi-calendar\"></i> Start Date Time:{\" \"}\n {new Date(data.start).toLocaleDateString(\"en-us\", {\n hour: \"2-digit\",\n minute: \"numeric\",\n })}\n </span>\n <span>\n <i className=\"bi bi-calendar\"></i> End Date Time:{\" \"}\n {new Date(data.end).toLocaleDateString(\"en-us\", {\n hour: \"2-digit\",\n minute: \"numeric\",\n })}\n </span>\n </div>\n {data.extendedProps.description && (\n <div className=\"mb-3\">\n <h5 style={{ fontSize: 12, fontWeight: 700, marginBottom: 8 }}>\n DESCRIPTION\n </h5>\n <p>{data.extendedProps.description}</p>\n </div>\n )}\n {organizers.length > 0 && (\n <div className=\"mb-3\">\n <h5 style={{ fontSize: 12, fontWeight: 700, marginBottom: 8 }}>\n ORGANIZERS\n </h5>\n {organizers.map((organizer) => {\n const organizerProfile = Social.getr(`${organizer}/profile`);\n return (\n <span className=\"d-flex align-items-center gap-1\">\n <Widget\n src=\"mob.near/widget/Image\"\n loading=\"\"\n props={{\n image: organizerProfile.image,\n fallbackUrl:\n \"https://ipfs.near.social/ipfs/bafkreibas66y6ewop5ix2n6mgybpjz6epg7opqvcplmm5jw4jlhdik5nhe\",\n style: {\n width: 24,\n height: 24,\n borderRadius: 12,\n objectFit: \"cover\",\n },\n }}\n />\n {organizerProfile.name ??\n organizers[0] ??\n \"No name profile\"}\n </span>\n );\n })}\n </div>\n )}\n {hashtags.length > 0 && (\n <div className=\"mb-3\">\n <h5 style={{ fontSize: 12, fontWeight: 700, marginBottom: 8 }}>\n HASHTAGS\n </h5>\n <div className=\"d-flex align-items-center gap-2 flex-wrap\">\n {hashtags.map((tag) => (\n <Hashtag key={tag}>{tag}</Hashtag>\n ))}\n </div>\n </div>\n )}\n {data.extendedProps.location && (\n <span className=\"d-flex align-items-center gap-1 mb-3\">\n <i className=\"bi bi-geo-alt\"></i>\n {data?.extendedProps?.location}\n </span>\n )}\n </div>\n <div className=\"d-flex align-items-center gap-3\">\n <Button\n noLink={true}\n href={`${data?.url}`}\n target=\"_blank\"\n variant=\"primary\"\n >\n Join Now\n </Button>\n {data.extendedProps.customButtonSrc && (\n <Widget src={data.extendedProps.customButtonSrc} loading=\"\" />\n )}\n </div>\n </Modal>\n )}\n </>\n);\n" } } } } }
Result:
{ "block_height": "113868801" }
No logs
Receipt:
Predecessor ID:
Receiver ID:
Gas Burned:
223 Ggas
Tokens Burned:
0 
Transferred 0.18764  to buildhub.near
Empty result
No logs