@levo-so/blocks 0.1.58 → 0.1.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/package.json +16 -15
  2. package/src/blocks/about-us/about-us-1.schema.ts +75 -58
  3. package/src/blocks/about-us/about-us-2.schema.ts +186 -39
  4. package/src/blocks/blogs/blog-listing-1.tsx +17 -15
  5. package/src/blocks/blogs/blog-listing-2.tsx +17 -15
  6. package/src/blocks/blogs/blog-listing-3.tsx +17 -15
  7. package/src/blocks/calendar/calendar-1.schema.ts +263 -181
  8. package/src/blocks/calendar/calendar-1.tsx +42 -11
  9. package/src/blocks/cards/cards-10.schema.ts +322 -313
  10. package/src/blocks/cards/cards-10.tsx +9 -1
  11. package/src/blocks/cards/cards-11.schema.ts +139 -248
  12. package/src/blocks/cards/cards-12.schema.ts +117 -196
  13. package/src/blocks/cards/cards-13.schema.ts +107 -56
  14. package/src/blocks/cards/cards-14.schema.ts +58 -154
  15. package/src/blocks/cards/cards-15.schema.ts +54 -31
  16. package/src/blocks/cards/cards-15.tsx +13 -2
  17. package/src/blocks/cards/cards-2.schema.ts +83 -88
  18. package/src/blocks/cards/cards-2.tsx +10 -2
  19. package/src/blocks/cards/cards-3.schema.ts +75 -70
  20. package/src/blocks/cards/cards-4.schema.ts +149 -91
  21. package/src/blocks/cards/cards-4.tsx +13 -2
  22. package/src/blocks/cards/cards-5.schema.ts +91 -68
  23. package/src/blocks/cards/cards-5.tsx +9 -1
  24. package/src/blocks/cards/cards-6.schema.ts +794 -972
  25. package/src/blocks/cards/cards-6.tsx +18 -2
  26. package/src/blocks/cards/cards-7.schema.ts +802 -2250
  27. package/src/blocks/cards/cards-7.tsx +14 -1
  28. package/src/blocks/cards/cards-8.schema.ts +166 -347
  29. package/src/blocks/cards/cards-8.tsx +14 -1
  30. package/src/blocks/cards/cards-9.schema.ts +300 -305
  31. package/src/blocks/cards/cards-9.tsx +27 -3
  32. package/src/blocks/carousel/carousel-1.schema.ts +479 -46
  33. package/src/blocks/carousel/carousel-1.tsx +2 -0
  34. package/src/blocks/carousel/carousel-2.schema.ts +170 -118
  35. package/src/blocks/carousel/carousel-2.tsx +10 -2
  36. package/src/blocks/community/community-1.schema.ts +566 -0
  37. package/src/blocks/community/community-1.tsx +690 -0
  38. package/src/blocks/community/community-post-1.schema.ts +417 -0
  39. package/src/blocks/community/community-post-1.tsx +155 -0
  40. package/src/blocks/contact-us/contact-us-1.schema.ts +33 -43
  41. package/src/blocks/contact-us/contact-us-2.schema.ts +39 -17
  42. package/src/blocks/contact-us/contact-us-2.tsx +1 -1
  43. package/src/blocks/content/content-1.schema.ts +184 -234
  44. package/src/blocks/content/content-1.tsx +48 -38
  45. package/src/blocks/content/content-2.schema.ts +143 -32
  46. package/src/blocks/content/content-2.tsx +15 -3
  47. package/src/blocks/content/content-3.schema.ts +215 -205
  48. package/src/blocks/content/content-3.tsx +13 -1
  49. package/src/blocks/content/content-4.schema.ts +124 -85
  50. package/src/blocks/content/content-4.tsx +2 -1
  51. package/src/blocks/content/content-5.schema.ts +296 -278
  52. package/src/blocks/content/content-5.tsx +23 -2
  53. package/src/blocks/content/content-6.schema.ts +474 -244
  54. package/src/blocks/content/content-6.tsx +23 -1
  55. package/src/blocks/content/content-7.schema.ts +173 -133
  56. package/src/blocks/content/content-7.tsx +27 -3
  57. package/src/blocks/content/content-8.schema.ts +27 -17
  58. package/src/blocks/content/content-9.schema.ts +64 -2208
  59. package/src/blocks/content/content-9.tsx +6 -3
  60. package/src/blocks/cta/cta-1.schema.ts +13 -108
  61. package/src/blocks/cta/cta-2.schema.ts +60 -69
  62. package/src/blocks/cta/cta-3.schema.ts +97 -66
  63. package/src/blocks/embed/embed-1.schema.ts +30 -52
  64. package/src/blocks/event/event-details.schema.ts +7 -0
  65. package/src/blocks/event/event-details.tsx +1 -0
  66. package/src/blocks/event/event-listing-2.tsx +17 -15
  67. package/src/blocks/event/event-listing-3.tsx +17 -15
  68. package/src/blocks/event/event-listing-4.tsx +17 -15
  69. package/src/blocks/event/event-listing.tsx +17 -15
  70. package/src/blocks/faq/faq-1.schema.ts +158 -112
  71. package/src/blocks/faq/faq-1.tsx +12 -3
  72. package/src/blocks/faq/faq-2.schema.ts +137 -74
  73. package/src/blocks/faq/faq-2.tsx +10 -1
  74. package/src/blocks/faq/faq-3.schema.ts +185 -105
  75. package/src/blocks/faq/faq-3.tsx +19 -3
  76. package/src/blocks/features/features-1/features-1.schema.ts +11 -3
  77. package/src/blocks/features/features-1/features-1.tsx +10 -1
  78. package/src/blocks/features/features-1/variants/default.ts +172 -54
  79. package/src/blocks/features/features-1/variants/stylized-cards-v1.ts +392 -54
  80. package/src/blocks/features/features-1/variants/stylized-cards-v2.ts +119 -103
  81. package/src/blocks/features/features-1/variants/stylized-cards-v3.ts +16 -199
  82. package/src/blocks/features/features-2.schema.ts +178 -45
  83. package/src/blocks/features/features-2.tsx +10 -2
  84. package/src/blocks/features/features-3.schema.ts +284 -65
  85. package/src/blocks/features/features-3.tsx +22 -3
  86. package/src/blocks/features/features-4.schema.ts +380 -185
  87. package/src/blocks/features/features-4.tsx +9 -1
  88. package/src/blocks/features/features-5.schema.ts +194 -198
  89. package/src/blocks/features/features-5.tsx +12 -1
  90. package/src/blocks/features/features-6.schema.ts +240 -193
  91. package/src/blocks/features/features-6.tsx +16 -2
  92. package/src/blocks/floating-buttons/floating-button-1.schema.ts +105 -0
  93. package/src/blocks/floating-buttons/floating-button-1.tsx +20 -0
  94. package/src/blocks/footer/footer-1.schema.ts +118 -48
  95. package/src/blocks/footer/footer-1.tsx +2 -1
  96. package/src/blocks/footer/footer-2.schema.ts +235 -31
  97. package/src/blocks/footer/footer-2.tsx +2 -1
  98. package/src/blocks/footer/footer-3.schema.ts +334 -57
  99. package/src/blocks/footer/footer-3.tsx +2 -1
  100. package/src/blocks/footer/footer-4.schema.ts +147 -76
  101. package/src/blocks/footer/footer-4.tsx +2 -1
  102. package/src/blocks/footer/footer-5.schema.ts +144 -52
  103. package/src/blocks/footer/footer-5.tsx +2 -1
  104. package/src/blocks/footer/footer-6.schema.ts +68 -140
  105. package/src/blocks/footer/footer-6.tsx +2 -1
  106. package/src/blocks/hero/hero-1.schema.ts +184 -87
  107. package/src/blocks/hero/hero-10.schema.ts +8 -29
  108. package/src/blocks/hero/hero-11.schema.ts +192 -89
  109. package/src/blocks/hero/hero-11.tsx +1 -1
  110. package/src/blocks/hero/hero-12.schema.ts +107 -170
  111. package/src/blocks/hero/hero-12.tsx +1 -1
  112. package/src/blocks/hero/hero-13.schema.ts +42 -28
  113. package/src/blocks/hero/hero-2.schema.ts +33 -58
  114. package/src/blocks/hero/hero-3.schema.ts +42 -34
  115. package/src/blocks/hero/hero-4.schema.ts +265 -70
  116. package/src/blocks/hero/hero-4.tsx +19 -2
  117. package/src/blocks/hero/hero-5.schema.ts +122 -44
  118. package/src/blocks/hero/hero-5.tsx +14 -2
  119. package/src/blocks/hero/hero-6.schema.ts +159 -255
  120. package/src/blocks/hero/hero-7.schema.ts +105 -34
  121. package/src/blocks/hero/hero-7.tsx +4 -1
  122. package/src/blocks/hero/hero-8.schema.ts +363 -133
  123. package/src/blocks/hero/hero-8.tsx +27 -3
  124. package/src/blocks/hero/hero-9.schema.ts +116 -83
  125. package/src/blocks/hero/hero-9.tsx +9 -1
  126. package/src/blocks/index.ts +7 -0
  127. package/src/blocks/logos/logos-1.schema.ts +424 -30
  128. package/src/blocks/polling/polling-1.schema.ts +1 -19
  129. package/src/blocks/pricing/pricing-1.schema.ts +296 -266
  130. package/src/blocks/pricing/pricing-1.tsx +16 -2
  131. package/src/blocks/products/products-listing-1.schema.ts +144 -33
  132. package/src/blocks/products/products-listing-1.tsx +9 -1
  133. package/src/blocks/products/products-listing-2.schema.ts +199 -213
  134. package/src/blocks/products/products-listing-2.tsx +25 -3
  135. package/src/blocks/products/products-listing-3.schema.ts +439 -154
  136. package/src/blocks/products/products-listing-3.tsx +43 -8
  137. package/src/blocks/profile/profile-1.schema.ts +67 -49
  138. package/src/blocks/profile/profile-1.tsx +3 -2
  139. package/src/blocks/profile/profile-2.schema.ts +73 -85
  140. package/src/blocks/profile/profile-2.tsx +2 -1
  141. package/src/blocks/profile/profile-3.schema.ts +162 -529
  142. package/src/blocks/profile/profile-3.tsx +2 -2
  143. package/src/blocks/services/service-1.schema.ts +204 -804
  144. package/src/blocks/services/service-1.tsx +15 -2
  145. package/src/blocks/services/service-2.schema.ts +95 -75
  146. package/src/blocks/services/service-2.tsx +9 -1
  147. package/src/blocks/services/service-3.schema.ts +73 -73
  148. package/src/blocks/services/service-3.tsx +40 -39
  149. package/src/blocks/stats/stats-1.schema.ts +225 -21
  150. package/src/blocks/stats/stats-1.tsx +4 -0
  151. package/src/blocks/stats/stats-2.schema.ts +13 -5
  152. package/src/blocks/stats/stats-2.tsx +9 -1
  153. package/src/blocks/stats/variants/default.ts +59 -41
  154. package/src/blocks/stats/variants/hero.ts +64 -31
  155. package/src/blocks/tabs/tab-1.schema.ts +105 -407
  156. package/src/blocks/tabs/tab-1.tsx +15 -4
  157. package/src/blocks/tabs/tab-2.schema.ts +208 -278
  158. package/src/blocks/tabs/tab-2.tsx +14 -2
  159. package/src/blocks/team/team-1.schema.ts +621 -76
  160. package/src/blocks/team/team-1.tsx +9 -1
  161. package/src/blocks/team/team-2.schema.ts +693 -1421
  162. package/src/blocks/team/team-2.tsx +4 -1
  163. package/src/blocks/team/team-3.schema.ts +147 -74
  164. package/src/blocks/team/team-3.tsx +1 -0
  165. package/src/blocks/team/team-4.schema.ts +216 -57
  166. package/src/blocks/team/team-4.tsx +10 -2
  167. package/src/blocks/team/team-5.schema.ts +67 -42
  168. package/src/blocks/team/team-5.tsx +12 -3
  169. package/src/blocks/termsAndPrivacy/terms-and-conditions-1.schema.ts +9 -26
  170. package/src/blocks/termsAndPrivacy/terms-and-conditions-1.tsx +1 -1
  171. package/src/blocks/testimonial/testimonial-1.schema.ts +712 -63
  172. package/src/blocks/testimonial/testimonial-1.tsx +2 -4
  173. package/src/blocks/testimonial/testimonial-2.schema.ts +1332 -354
  174. package/src/blocks/testimonial/testimonial-2.tsx +4 -1
  175. package/src/blocks/testimonial/testimonial-3.schema.ts +215 -71
  176. package/src/blocks/testimonial/testimonial-3.tsx +5 -2
  177. package/src/blocks/testimonial/testimonial-4.schema.ts +331 -933
  178. package/src/blocks/testimonial/testimonial-4.tsx +4 -1
  179. package/src/blocks/testimonial/testimonial-5/variants/default.ts +179 -171
  180. package/src/blocks/testimonial/testimonial-5/variants/testimonialWithLogo.ts +205 -501
  181. package/src/blocks/testimonial/testimonial-5/variants/testimonialWithRatings.ts +190 -316
  182. package/src/blocks/testimonial/testimonial-6.schema.ts +204 -267
  183. package/src/blocks/testimonial/testimonial-7.schema.ts +74 -45
  184. package/src/blocks/testimonial/testimonial-7.tsx +2 -2
  185. package/src/blocks/timeline/timeline-1.schema.ts +196 -149
  186. package/src/blocks/timeline/timeline-1.tsx +4 -1
  187. package/src/blocks/users/edit-profile.schema.ts +56 -44
  188. package/src/blocks/users/edit-profile.tsx +13 -6
  189. package/src/constants/index.ts +19 -0
  190. package/src/schemas/blocks.ts +6 -0
  191. package/src/schemas/categories.ts +12 -0
@@ -0,0 +1,690 @@
1
+ import {
2
+ type ILevoBlockBaseProps,
3
+ Heading,
4
+ Typography,
5
+ Container,
6
+ Section,
7
+ Box,
8
+ ForumPost,
9
+ Button,
10
+ Skeleton,
11
+ Image,
12
+ Media,
13
+ } from "@levo-so/studio";
14
+ import { useCallback, useEffect, useRef, useState } from "react";
15
+ import { useLevo } from "@levo-so/react";
16
+ import type {
17
+ IForumPost,
18
+ ILevoMembership,
19
+ IResponseMultiple,
20
+ } from "@levo-so/core";
21
+
22
+ import type { ICommunity1Content } from "./community-1.schema";
23
+
24
+ const LINK_METADATA = {
25
+ url: "https://example.com/renewable-energy-breakthrough",
26
+ title: "New Battery Technology Increases Storage Capacity by 300%",
27
+ description:
28
+ "Researchers at MIT have developed a revolutionary battery technology that could transform renewable energy storage, making solar and wind power more viable for 24/7 use.",
29
+ image: "https://picsum.photos/800/400?random=4",
30
+ domain: "example.com",
31
+ };
32
+
33
+ const TEST_USER: ILevoMembership.Account = {
34
+ _id: "USER_ID",
35
+ first_name: "Jane",
36
+ last_name: "Doe",
37
+ slug: "jane-doe",
38
+ username: "janedoeofficial",
39
+ email: "jane@example.com",
40
+ display_email: "jane@example.com",
41
+ reducted_email: "j***@e****.com",
42
+ email_verified: true,
43
+ email_verified_at: new Date().toISOString(),
44
+ verified_at: new Date().toISOString(),
45
+ mobile: null,
46
+ reducted_mobile: null,
47
+ mobile_verified: false,
48
+ mobile_verified_at: null,
49
+ profile_picture: {
50
+ id: "OaJDFLqx2UQyN",
51
+ kind: "image",
52
+ location: "https://github.com/shadcn.png",
53
+ srcset: {
54
+ "1080w": "https://github.com/shadcn.png",
55
+ "1200w": "https://github.com/shadcn.png",
56
+ "1920w": "https://github.com/shadcn.png",
57
+ "320w": "https://github.com/shadcn.png",
58
+ "640w": "https://github.com/shadcn.png",
59
+ "750w": "https://github.com/shadcn.png",
60
+ "828w": "https://github.com/shadcn.png",
61
+ path: "https://github.com/shadcn.png",
62
+ },
63
+ },
64
+ oauth_credentials: [],
65
+ account_locked_at: null,
66
+ credentials_expired_at: null,
67
+ deactivated_at: null,
68
+ last_access_at: new Date().toISOString(),
69
+ flagged_at: null,
70
+ created_at: new Date().toISOString(),
71
+ updated_at: new Date().toISOString(),
72
+ deleted_at: null,
73
+ };
74
+
75
+ const SAMPLE_FORUM_POSTS: IResponseMultiple<IForumPost> = {
76
+ content: {
77
+ data: [
78
+ {
79
+ _id: "7403047340596025651",
80
+ comments_count: 0,
81
+ content:
82
+ "<p>Hey, This is a content post. <br><br>Good Luck with the rest.</p>",
83
+ created_at: "2025-12-06T12:27:07.966Z",
84
+ created_by: TEST_USER,
85
+ expires_at: null,
86
+ kind: "post",
87
+ upvote_count: 50,
88
+ downvote_count: 10,
89
+ upvoted_at: null,
90
+ downvoted_at: "2025-12-06T12:28:33.774Z",
91
+ media: [],
92
+ metadata: null,
93
+ published_at: "2025-12-06T12:27:07.966Z",
94
+ show_participant_list: false,
95
+ show_participant_vote: true,
96
+ slug: "ui-content-post",
97
+ url: "",
98
+ title: "UI: Content Post",
99
+ updated_at: "2025-12-06T12:27:07.966Z",
100
+ deleted_at: null,
101
+ deleted_by: null,
102
+ vote_count: null,
103
+ options: [],
104
+ },
105
+ {
106
+ _id: "7403047700499286828",
107
+ comments_count: 0,
108
+ content:
109
+ "<p>This is a gallery post.<br><br>Good Luck with the rest.</p>",
110
+ created_at: "2025-12-06T12:28:33.774Z",
111
+ created_by: null,
112
+ expires_at: null,
113
+ kind: "gallery",
114
+ upvoted_at: "2025-12-06T12:28:33.774Z",
115
+ downvoted_at: null,
116
+ upvote_count: 23,
117
+ downvote_count: 66,
118
+ media: [
119
+ {
120
+ id: "uY2rOYbtH2WKZ",
121
+ location:
122
+ "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP.jpg",
123
+ mimetype: "image/jpeg",
124
+ kind: "image",
125
+ srcset: {
126
+ "1080w":
127
+ "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-1080w.webp",
128
+ "1200w":
129
+ "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-1200w.webp",
130
+ "1920w":
131
+ "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-1920w.webp",
132
+ "320w":
133
+ "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-320w.webp",
134
+ "640w":
135
+ "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-640w.webp",
136
+ "750w":
137
+ "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-750w.webp",
138
+ "828w":
139
+ "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-828w.webp",
140
+ path: "https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-1080w.webp 1080w, https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-1200w.webp 1200w, https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-1920w.webp 1920w, https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-320w.webp 320w, https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-640w.webp 640w, https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-750w.webp 750w, https://static.levostg.online/WZZKMUBH/wp2845973-itachi-anbu-wallpaper-CISpLrr9FxcTP-828w.webp 828w",
141
+ },
142
+ },
143
+ {
144
+ id: "lDig3GwIc8cuX",
145
+ location:
146
+ "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr.jpg",
147
+ mimetype: "image/jpeg",
148
+ kind: "image",
149
+ srcset: {
150
+ "1080w":
151
+ "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-1080w.webp",
152
+ "1200w":
153
+ "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-1200w.webp",
154
+ "1920w":
155
+ "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-1920w.webp",
156
+ "320w":
157
+ "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-320w.webp",
158
+ "640w":
159
+ "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-640w.webp",
160
+ "750w":
161
+ "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-750w.webp",
162
+ "828w":
163
+ "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-828w.webp",
164
+ path: "https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-320w.webp 320w, https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-1080w.webp 1080w, https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-750w.webp 750w, https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-640w.webp 640w, https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-828w.webp 828w, https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-1200w.webp 1200w, https://static.levostg.online/WZZKMUBH/7-Must-Have-Features-for-a-Food-Beverage-ERP-system-Softype-Inc-Netsuite-Alliance-Partner-moxx13I6bnlIr-1920w.webp 1920w",
165
+ },
166
+ },
167
+ {
168
+ id: "MqnM9ygQVs3aI",
169
+ location:
170
+ "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3.jpg",
171
+ mimetype: "image/jpeg",
172
+ kind: "image",
173
+ srcset: {
174
+ "1080w":
175
+ "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-1080w.webp",
176
+ "1200w":
177
+ "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-1200w.webp",
178
+ "1920w":
179
+ "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-1920w.webp",
180
+ "320w":
181
+ "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-320w.webp",
182
+ "640w":
183
+ "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-640w.webp",
184
+ "750w":
185
+ "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-750w.webp",
186
+ "828w":
187
+ "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-828w.webp",
188
+ path: "https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-320w.webp 320w, https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-640w.webp 640w, https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-750w.webp 750w, https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-828w.webp 828w, https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-1080w.webp 1080w, https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-1200w.webp 1200w, https://static.levostg.online/WZZKMUBH/The-Future-of-Retail-Covid-19-Softype-Inc-Blog-Update-xloAzCSXADxN3-1920w.webp 1920w",
189
+ },
190
+ },
191
+ {
192
+ id: "xloJuCSXADUpL",
193
+ location:
194
+ "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm.jpg",
195
+ mimetype: "image/jpeg",
196
+ kind: "image",
197
+ srcset: {
198
+ "1080w":
199
+ "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-1080w.webp",
200
+ "1200w":
201
+ "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-1200w.webp",
202
+ "1920w":
203
+ "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-1920w.webp",
204
+ "320w":
205
+ "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-320w.webp",
206
+ "640w":
207
+ "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-640w.webp",
208
+ "750w":
209
+ "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-750w.webp",
210
+ "828w":
211
+ "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-828w.webp",
212
+ path: "https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-1920w.webp 1920w, https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-320w.webp 320w, https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-828w.webp 828w, https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-750w.webp 750w, https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-640w.webp 640w, https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-1200w.webp 1200w, https://static.levostg.online/WZZKMUBH/3-tips-for-successful-Accounts-Payable-Management-Softype-INC-4JOrxlk9pfgLm-1080w.webp 1080w",
213
+ },
214
+ },
215
+ {
216
+ id: "4JO75lk9pfVoz",
217
+ location:
218
+ "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk.jpg",
219
+ mimetype: "image/jpeg",
220
+ kind: "image",
221
+ srcset: {
222
+ "1080w":
223
+ "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-1080w.webp",
224
+ "1200w":
225
+ "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-1200w.webp",
226
+ "1920w":
227
+ "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-1920w.webp",
228
+ "320w":
229
+ "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-320w.webp",
230
+ "640w":
231
+ "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-640w.webp",
232
+ "750w":
233
+ "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-750w.webp",
234
+ "828w":
235
+ "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-828w.webp",
236
+ path: "https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-1200w.webp 1200w, https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-1920w.webp 1920w, https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-320w.webp 320w, https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-640w.webp 640w, https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-750w.webp 750w, https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-1080w.webp 1080w, https://static.levostg.online/WZZKMUBH/shutterstock572315812-xloAsCSXADxFk-828w.webp 828w",
237
+ },
238
+ },
239
+ {
240
+ id: "1d74SLgA5aCsp",
241
+ location:
242
+ "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D.jpg",
243
+ mimetype: "image/jpeg",
244
+ kind: "image",
245
+ srcset: {
246
+ "1080w":
247
+ "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-1080w.webp",
248
+ "1200w":
249
+ "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-1200w.webp",
250
+ "1920w":
251
+ "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-1920w.webp",
252
+ "320w":
253
+ "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-320w.webp",
254
+ "640w":
255
+ "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-640w.webp",
256
+ "750w":
257
+ "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-750w.webp",
258
+ "828w":
259
+ "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-828w.webp",
260
+ path: "https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-1920w.webp 1920w, https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-320w.webp 320w, https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-750w.webp 750w, https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-640w.webp 640w, https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-828w.webp 828w, https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-1080w.webp 1080w, https://static.levostg.online/WZZKMUBH/7-reasons-NetSuite-is-Worlds-1-Cloud-Financial-Accounting-Software-Softype-Inc-74dEtDIGEyR4D-1200w.webp 1200w",
261
+ },
262
+ },
263
+ {
264
+ id: "GLUJwcipcQ1DJ",
265
+ location:
266
+ "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX.jpg",
267
+ mimetype: "image/jpeg",
268
+ kind: "image",
269
+ srcset: {
270
+ "1080w":
271
+ "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-1080w.webp",
272
+ "1200w":
273
+ "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-1200w.webp",
274
+ "1920w":
275
+ "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-1920w.webp",
276
+ "320w":
277
+ "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-320w.webp",
278
+ "640w":
279
+ "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-640w.webp",
280
+ "750w":
281
+ "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-750w.webp",
282
+ "828w":
283
+ "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-828w.webp",
284
+ path: "https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-320w.webp 320w, https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-640w.webp 640w, https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-828w.webp 828w, https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-750w.webp 750w, https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-1080w.webp 1080w, https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-1200w.webp 1200w, https://static.levostg.online/WZZKMUBH/Building-an-Effective-and-Efficient-Sales-Workforce-in-the-New-Normal-Softype-Inc-XZbIObcKFJZWX-1920w.webp 1920w",
285
+ },
286
+ },
287
+ {
288
+ id: "A8sdO1BeFXg2Q",
289
+ location:
290
+ "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz.jpg",
291
+ mimetype: "image/jpeg",
292
+ kind: "image",
293
+ srcset: {
294
+ "1080w":
295
+ "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-1080w.webp",
296
+ "1200w":
297
+ "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-1200w.webp",
298
+ "1920w":
299
+ "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-1920w.webp",
300
+ "320w":
301
+ "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-320w.webp",
302
+ "640w":
303
+ "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-640w.webp",
304
+ "750w":
305
+ "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-750w.webp",
306
+ "828w":
307
+ "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-828w.webp",
308
+ path: "https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-828w.webp 828w, https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-1080w.webp 1080w, https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-1200w.webp 1200w, https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-1920w.webp 1920w, https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-320w.webp 320w, https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-750w.webp 750w, https://static.levostg.online/WZZKMUBH/Learning-to-Go-Live-Lessons-From-The-Pandemic-Trenches-Softype-INC-30WLnpdHjSoUz-640w.webp 640w",
309
+ },
310
+ },
311
+ ],
312
+ metadata: null,
313
+ published_at: "2025-12-06T12:28:33.774Z",
314
+ show_participant_list: false,
315
+ show_participant_vote: true,
316
+ slug: "ui-gallery-post",
317
+ url: "",
318
+ title: "UI: Gallery Post",
319
+ updated_at: "2025-12-06T12:28:33.774Z",
320
+ deleted_at: null,
321
+ deleted_by: null,
322
+ vote_count: null,
323
+ options: [],
324
+ },
325
+ {
326
+ _id: "7403048140069180235",
327
+ comments_count: 0,
328
+ content:
329
+ "<p>Hey, This is a Poll Post.<br><br>Good Luck with the rest.</p>",
330
+ created_at: "2025-12-06T12:30:18.575Z",
331
+ created_by: TEST_USER,
332
+ expires_at: "2026-12-31T12:30:00.000Z",
333
+ kind: "poll",
334
+ upvoted_at: "2025-12-06T12:28:33.774Z",
335
+ downvoted_at: null,
336
+ upvote_count: 100,
337
+ downvote_count: 1,
338
+ media: [],
339
+ metadata: null,
340
+ published_at: "2025-12-06T12:30:18.575Z",
341
+ show_participant_list: true,
342
+ show_participant_vote: true,
343
+ slug: "ui-this-is-a-poll",
344
+ url: "",
345
+ title: "UI: Poll Post",
346
+ updated_at: "2025-12-06T12:30:18.575Z",
347
+ deleted_at: null,
348
+ deleted_by: null,
349
+ vote_count: 16,
350
+ user_voted_option: "7403048138708901408",
351
+ options: [
352
+ {
353
+ _id: "7403048138708668754",
354
+ label: "Poll Option 1",
355
+ count: 4,
356
+ },
357
+ {
358
+ _id: "7403048138710723182",
359
+ label: "Poll Option 2",
360
+ count: 8,
361
+ },
362
+ {
363
+ _id: "7403048138708304207",
364
+ label: "Poll Option 3",
365
+ count: 3,
366
+ },
367
+ {
368
+ _id: "7403048138708901408",
369
+ label: "Poll Option 4",
370
+ count: 1,
371
+ },
372
+ ],
373
+ },
374
+ {
375
+ _id: "7403048494051511085",
376
+ comments_count: 0,
377
+ content:
378
+ "<p>Hey, This is a link post.<br><br>Good luck with the rest.</p>",
379
+ created_at: "2025-12-06T12:31:42.971Z",
380
+ created_by: TEST_USER,
381
+ expires_at: null,
382
+ kind: "link",
383
+ upvoted_at: null,
384
+ downvoted_at: "2025-12-06T12:28:33.774Z",
385
+ upvote_count: 60,
386
+ downvote_count: 10,
387
+ media: [],
388
+ metadata: null,
389
+ published_at: "2025-12-06T12:31:42.971Z",
390
+ show_participant_list: false,
391
+ show_participant_vote: true,
392
+ slug: "ui-link-post",
393
+ url: "https://www.youtube.com/",
394
+ title: "UI: Link Post",
395
+ updated_at: "2025-12-06T12:31:42.971Z",
396
+ deleted_at: null,
397
+ deleted_by: null,
398
+ vote_count: null,
399
+ options: [],
400
+ },
401
+ {
402
+ _id: "7403048494051511085",
403
+ comments_count: 0,
404
+ content:
405
+ "<p>Hey, This is a link post.<br><br>Good luck with the rest.</p>",
406
+ created_at: "2025-12-06T12:31:42.971Z",
407
+ created_by: TEST_USER,
408
+ expires_at: null,
409
+ kind: "link",
410
+ upvote_count: 50,
411
+ downvote_count: 97,
412
+ upvoted_at: null,
413
+ downvoted_at: "2025-12-06T12:28:33.774Z",
414
+ media: [],
415
+ metadata: {
416
+ meta_title: LINK_METADATA?.title,
417
+ meta_description: LINK_METADATA?.description,
418
+ og_image: {
419
+ id: "uY2rOYbtH2WKZ",
420
+ location: LINK_METADATA?.image,
421
+ mimetype: "image/jpeg",
422
+ kind: "image",
423
+ },
424
+ },
425
+ published_at: "2025-12-06T12:31:42.971Z",
426
+ show_participant_list: false,
427
+ show_participant_vote: true,
428
+ slug: "ui-link-post-2",
429
+ url: LINK_METADATA?.url,
430
+ title: "UI: Link Post 2",
431
+ updated_at: "2025-12-06T12:31:42.971Z",
432
+ deleted_at: null,
433
+ deleted_by: null,
434
+ vote_count: null,
435
+ options: [],
436
+ },
437
+ ] as any,
438
+
439
+ meta: {
440
+ pages: 1,
441
+ total: 2,
442
+ },
443
+ },
444
+ status: true,
445
+ };
446
+
447
+ const PostSkeleton: React.FC = () => {
448
+ return (
449
+ <div className="flex flex-col gap-3 rounded-lg border border-[#E5E5E5] bg-white p-3">
450
+ {/* Header */}
451
+ <div className="flex items-center gap-2">
452
+ <Skeleton className="h-8.5 w-8.5 rounded-full" />
453
+ <div className="flex items-center gap-1">
454
+ <Skeleton className="h-4 w-24" />
455
+ <Skeleton className="h-3 w-16" />
456
+ </div>
457
+ </div>
458
+
459
+ {/* Title and Content */}
460
+ <div className="space-y-2">
461
+ <Skeleton className="h-5 w-3/4" />
462
+ <div className="space-y-2">
463
+ <Skeleton className="h-4 w-full" />
464
+ <Skeleton className="h-4 w-full" />
465
+ <Skeleton className="h-4 w-2/3" />
466
+ </div>
467
+ </div>
468
+
469
+ {/* Actions */}
470
+ <div className="mt-3 flex items-center gap-4">
471
+ <Skeleton className="h-8 w-20 rounded-lg" />
472
+ <Skeleton className="h-8 w-16 rounded-lg" />
473
+ <Skeleton className="h-8 w-20 rounded-lg" />
474
+ </div>
475
+ </div>
476
+ );
477
+ };
478
+
479
+ const MAX_RETRY_ATTEMPTS = 3;
480
+
481
+ const Community1: React.FC<ILevoBlockBaseProps<ICommunity1Content>> = ({
482
+ content,
483
+ }) => {
484
+ const levoClient = useLevo();
485
+ const observerTarget = useRef<HTMLDivElement>(null);
486
+
487
+ const [isLoading, setIsLoading] = useState(true);
488
+ const [isFetchingMore, setIsFetchingMore] = useState(false);
489
+ const [forumPosts, setForumPosts] = useState<IForumPost[]>([]);
490
+ const [page, setPage] = useState(1);
491
+ const [hasMore, setHasMore] = useState(true);
492
+ const [failedAttempts, setFailedAttempts] = useState(0);
493
+ const [hasError, setHasError] = useState(false);
494
+
495
+ const fetchPolls = useCallback(
496
+ async (pageNumber: number, append = false) => {
497
+ if (append) {
498
+ setIsFetchingMore(true);
499
+ } else {
500
+ setIsLoading(true);
501
+ }
502
+
503
+ try {
504
+ const response = await levoClient.fetch
505
+ .url("/v1/community/forum/posts/list")
506
+ .post({
507
+ limit: 10,
508
+ page: pageNumber,
509
+ sort: {
510
+ created_at: "desc",
511
+ },
512
+ })
513
+
514
+ .json<IResponseMultiple<IForumPost>>();
515
+
516
+ if (response && response?.content?.data) {
517
+ const newPosts = response.content.data;
518
+ const totalPages = response.content.meta?.pages || 1;
519
+
520
+ setForumPosts((prev) => (append ? [...prev, ...newPosts] : newPosts));
521
+ setHasMore(pageNumber < totalPages);
522
+ setFailedAttempts(0);
523
+ setHasError(false);
524
+ }
525
+ } catch (err: unknown) {
526
+ console.error("Failed to fetch forum posts:", err);
527
+
528
+ setFailedAttempts((prev) => prev + 1);
529
+
530
+ if (failedAttempts + 1 >= MAX_RETRY_ATTEMPTS) {
531
+ setHasError(true);
532
+ setHasMore(false);
533
+ }
534
+ } finally {
535
+ setIsLoading(false);
536
+ setIsFetchingMore(false);
537
+ }
538
+ },
539
+ [levoClient, failedAttempts],
540
+ );
541
+
542
+ useEffect(() => {
543
+ fetchPolls(1, false);
544
+ }, []);
545
+
546
+ useEffect(() => {
547
+ const observer = new IntersectionObserver(
548
+ (entries) => {
549
+ const entry = entries[0];
550
+ if (
551
+ entry &&
552
+ entry.isIntersecting &&
553
+ hasMore &&
554
+ !isLoading &&
555
+ !isFetchingMore &&
556
+ !hasError
557
+ ) {
558
+ const nextPage = page + 1;
559
+ setPage(nextPage);
560
+ fetchPolls(nextPage, true);
561
+ }
562
+ },
563
+ { threshold: 0.1 },
564
+ );
565
+
566
+ const currentTarget = observerTarget.current;
567
+ if (currentTarget) {
568
+ observer.observe(currentTarget);
569
+ }
570
+
571
+ return () => {
572
+ if (currentTarget) {
573
+ observer.unobserve(currentTarget);
574
+ }
575
+ };
576
+ }, [hasMore, isLoading, isFetchingMore, hasError, page, fetchPolls]);
577
+
578
+ return (
579
+ <Section elementKey="layout">
580
+ <Container elementKey="container">
581
+ <Box elementKey="content_section">
582
+ <Box elementKey="left_container">
583
+ <Box elementKey="sidebar_links_levoGroup">
584
+ {content?.sidebar_links?.map((v, index) => {
585
+ return (
586
+ <Button
587
+ key={`sidebar_links.${index}.sidebar_link`}
588
+ elementKey={`sidebar_links.${index}.sidebar_link`}
589
+ />
590
+ );
591
+ })}
592
+ </Box>
593
+ </Box>
594
+
595
+ <Box elementKey="feed_container">
596
+ <Box elementKey="header">
597
+ <Heading elementKey="title" />
598
+ <Typography elementKey="description" />
599
+ </Box>
600
+ <Box elementKey="posts">
601
+ {isLoading ? (
602
+ <>
603
+ <PostSkeleton />
604
+ <PostSkeleton />
605
+ <PostSkeleton />
606
+ <PostSkeleton />
607
+ </>
608
+ ) : (
609
+ <>
610
+ {forumPosts?.map((item, index: number) => (
611
+ <ForumPost
612
+ key={`polls.${index}`}
613
+ post={item}
614
+ postDetailPageBaseURL={
615
+ content?.post_detail_page_url || ""
616
+ }
617
+ />
618
+ ))}
619
+
620
+ {hasMore && !hasError && (
621
+ <div ref={observerTarget} className="h-4" />
622
+ )}
623
+
624
+ {isFetchingMore && (
625
+ <>
626
+ <PostSkeleton />
627
+ <PostSkeleton />
628
+ </>
629
+ )}
630
+
631
+ {hasError && (
632
+ <Box
633
+ elementKey="error_container"
634
+ style={{
635
+ display: "flex",
636
+ alignItems: "center",
637
+ justifyContent: "center",
638
+ minHeight: "16rem",
639
+ }}
640
+ >
641
+ <Typography
642
+ elementKey="error_text"
643
+ className="text-sm font-medium text-red-600"
644
+ >
645
+ Failed to load posts after {MAX_RETRY_ATTEMPTS}{" "}
646
+ attempts. Please try refreshing the page.
647
+ </Typography>
648
+ </Box>
649
+ )}
650
+ </>
651
+ )}
652
+ </Box>
653
+ </Box>
654
+ <Box elementKey="right_container">
655
+ <Box elementKey="edit_profile_block">
656
+ <Box elementKey="edit_profile_block_content_wrapper">
657
+ <Media
658
+ elementKey="edit_profile_block_banner_image"
659
+ alt="Banner Image"
660
+ />
661
+ <Box elementKey="edit_profile_block_content">
662
+ <Media
663
+ elementKey="edit_profile_block_logo"
664
+ alt="Community Logo"
665
+ />
666
+ <Box elementKey="edit_profile_block_text_container">
667
+ <Heading elementKey="edit_profile_block_title" />
668
+ <Typography elementKey="edit_profile_block_description" />
669
+ </Box>
670
+ </Box>
671
+ </Box>
672
+ <Box elementKey="edit_profile_ctas_levoGroup">
673
+ {content?.edit_profile_ctas?.map((v, index) => {
674
+ return (
675
+ <Button
676
+ key={`edit_profile_ctas.${index}.edit_profile_cta`}
677
+ elementKey={`edit_profile_ctas.${index}.edit_profile_cta`}
678
+ />
679
+ );
680
+ })}
681
+ </Box>
682
+ </Box>
683
+ </Box>
684
+ </Box>
685
+ </Container>
686
+ </Section>
687
+ );
688
+ };
689
+
690
+ export default Community1;