@myrjfa/ui 1.1.0 → 1.1.1
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.
- package/dist/chat/ChatMain.d.ts.map +1 -1
- package/dist/chat/ChatMain.js +173 -145
- package/dist/chat/ChatSidebar.js +7 -8
- package/dist/chat/ConversationList.d.ts.map +1 -1
- package/dist/chat/ConversationList.js +20 -18
- package/dist/chat/ExpensePanel.d.ts +4 -1
- package/dist/chat/ExpensePanel.d.ts.map +1 -1
- package/dist/chat/ExpensePanel.js +215 -195
- package/dist/chat/MessageBubble.d.ts +5 -3
- package/dist/chat/MessageBubble.d.ts.map +1 -1
- package/dist/chat/MessageBubble.js +185 -103
- package/dist/chat/MessageInput.d.ts +8 -1
- package/dist/chat/MessageInput.d.ts.map +1 -1
- package/dist/chat/MessageInput.js +182 -165
- package/dist/chat/MilestonePanel.d.ts +4 -1
- package/dist/chat/MilestonePanel.d.ts.map +1 -1
- package/dist/chat/MilestonePanel.js +150 -150
- package/dist/chat/components/ParticipantSelector.d.ts +11 -0
- package/dist/chat/components/ParticipantSelector.d.ts.map +1 -0
- package/dist/chat/components/ParticipantSelector.js +17 -0
- package/dist/chat/components/SplitInputs.d.ts +11 -0
- package/dist/chat/components/SplitInputs.d.ts.map +1 -0
- package/dist/chat/components/SplitInputs.js +83 -0
- package/dist/chat/components/SplitTypeSelector.d.ts +8 -0
- package/dist/chat/components/SplitTypeSelector.d.ts.map +1 -0
- package/dist/chat/components/SplitTypeSelector.js +13 -0
- package/dist/chat/dialogs/AddMemberDialog.js +30 -90
- package/dist/chat/dialogs/CameraDialog.js +38 -86
- package/dist/chat/dialogs/CreatePollDialog.d.ts +8 -0
- package/dist/chat/dialogs/CreatePollDialog.d.ts.map +1 -0
- package/dist/chat/dialogs/CreatePollDialog.js +38 -0
- package/dist/chat/dialogs/ExpenseAnalyticsDialog.d.ts +19 -0
- package/dist/chat/dialogs/ExpenseAnalyticsDialog.d.ts.map +1 -0
- package/dist/chat/dialogs/ExpenseAnalyticsDialog.js +52 -0
- package/dist/chat/dialogs/GroupInfoDialog.d.ts.map +1 -1
- package/dist/chat/dialogs/GroupInfoDialog.js +55 -92
- package/dist/chat/dialogs/GroupInfoViewDialog.js +5 -6
- package/dist/chat/dialogs/NewChatDialog.d.ts.map +1 -1
- package/dist/chat/dialogs/NewChatDialog.js +49 -113
- package/dist/chat/dialogs/NewGroupDialog.d.ts.map +1 -1
- package/dist/chat/dialogs/NewGroupDialog.js +49 -92
- package/dist/chat/dialogs/ParticipantsDialog.d.ts.map +1 -1
- package/dist/chat/dialogs/ParticipantsDialog.js +68 -118
- package/dist/chat/dialogs/UserProfileDialog.d.ts +10 -0
- package/dist/chat/dialogs/UserProfileDialog.d.ts.map +1 -0
- package/dist/chat/dialogs/UserProfileDialog.js +100 -0
- package/dist/dashboard/action-buttons.js +4 -5
- package/dist/dashboard/app-sidebar.js +46 -128
- package/dist/dashboard/card-header.js +1 -2
- package/dist/dashboard/dashboard-components.js +3 -5
- package/dist/dashboard/data-table.js +21 -33
- package/dist/dashboard/nav-main.js +4 -5
- package/dist/dashboard/nav-secondary.js +2 -25
- package/dist/dashboard/stats-card.js +1 -2
- package/dist/dashboard/table.js +8 -54
- package/dist/header/mobile-nav-item.js +1 -2
- package/dist/header/mobile-navbar.js +8 -9
- package/dist/header/nav-item.js +1 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/main/footer.js +5 -9
- package/dist/main/navbar.js +53 -136
- package/dist/main/paginationBar.js +12 -14
- package/dist/main/portfolio/portfolioItem.js +1 -2
- package/dist/main/portfolio/portfolioPopup.js +16 -17
- package/dist/main/review-page.d.ts.map +1 -1
- package/dist/main/review-page.js +131 -198
- package/dist/misc/accordion.js +8 -34
- package/dist/misc/alert-dialog.js +22 -55
- package/dist/misc/alert.js +7 -32
- package/dist/misc/alertdialogclaude.js +50 -125
- package/dist/misc/avatar.js +6 -31
- package/dist/misc/badge.js +4 -27
- package/dist/misc/button.js +4 -27
- package/dist/misc/card.js +12 -40
- package/dist/misc/carousel.js +37 -61
- package/dist/misc/checkbox.js +2 -25
- package/dist/misc/command.js +18 -49
- package/dist/misc/datepicker.js +66 -76
- package/dist/misc/dialog.js +20 -52
- package/dist/misc/dropdown-menu.js +30 -67
- package/dist/misc/faq.js +2 -3
- package/dist/misc/file-preview.js +43 -97
- package/dist/misc/filter.d.ts.map +1 -1
- package/dist/misc/filter.js +18 -21
- package/dist/misc/filterBar.js +136 -160
- package/dist/misc/form.js +39 -60
- package/dist/misc/image-cropper.d.ts +10 -0
- package/dist/misc/image-cropper.d.ts.map +1 -0
- package/dist/misc/image-cropper.js +44 -0
- package/dist/misc/input.js +2 -25
- package/dist/misc/label.js +2 -25
- package/dist/misc/line-carousel.js +3 -13
- package/dist/misc/multiImageUploader.js +2 -3
- package/dist/misc/newsLetter.js +18 -78
- package/dist/misc/notification.d.ts +1 -2
- package/dist/misc/notification.d.ts.map +1 -1
- package/dist/misc/notification.js +89 -125
- package/dist/misc/pagination.js +16 -45
- package/dist/misc/password-eye.js +2 -3
- package/dist/misc/popover.d.ts.map +1 -1
- package/dist/misc/popover.js +8 -34
- package/dist/misc/progress.js +2 -25
- package/dist/misc/scroll-area.js +5 -29
- package/dist/misc/searchBar.js +27 -31
- package/dist/misc/searchBox.js +18 -22
- package/dist/misc/select.d.ts.map +1 -1
- package/dist/misc/select.js +22 -54
- package/dist/misc/separator.js +2 -25
- package/dist/misc/share.js +48 -104
- package/dist/misc/sheet.js +21 -53
- package/dist/misc/sidebar.js +112 -153
- package/dist/misc/skeleton.js +2 -25
- package/dist/misc/slider.js +3 -26
- package/dist/misc/starRating.js +5 -15
- package/dist/misc/stateCard.js +7 -8
- package/dist/misc/switch.d.ts +5 -0
- package/dist/misc/switch.d.ts.map +1 -0
- package/dist/misc/switch.js +8 -0
- package/dist/misc/tabs.js +8 -34
- package/dist/misc/textarea.js +2 -25
- package/dist/misc/tile.js +31 -92
- package/dist/misc/tooltip.js +8 -34
- package/dist/profile/socialLink.d.ts +1 -1
- package/dist/profile/socialLink.d.ts.map +1 -1
- package/dist/profile/socialLink.js +53 -69
- package/dist/utils/permissions.d.ts +7 -0
- package/dist/utils/permissions.d.ts.map +1 -0
- package/dist/utils/permissions.js +38 -0
- package/package.json +3 -2
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
interface ImageCropperProps {
|
|
3
|
+
image: string;
|
|
4
|
+
onCancel: () => void;
|
|
5
|
+
onCropComplete: (croppedImage: Blob) => void;
|
|
6
|
+
open: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare const ImageCropper: React.FC<ImageCropperProps>;
|
|
9
|
+
export default ImageCropper;
|
|
10
|
+
//# sourceMappingURL=image-cropper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-cropper.d.ts","sourceRoot":"","sources":["../../src/misc/image-cropper.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAMrD,UAAU,iBAAiB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,EAAE,CAAC,YAAY,EAAE,IAAI,KAAK,IAAI,CAAC;IAC7C,IAAI,EAAE,OAAO,CAAC;CACjB;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgG7C,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useCallback } from "react";
|
|
4
|
+
import Cropper from "react-easy-crop";
|
|
5
|
+
import { Button } from "./button";
|
|
6
|
+
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "./dialog";
|
|
7
|
+
import { Slider } from "./slider";
|
|
8
|
+
const ImageCropper = ({ image, onCancel, onCropComplete, open }) => {
|
|
9
|
+
const [crop, setCrop] = useState({ x: 0, y: 0 });
|
|
10
|
+
const [zoom, setZoom] = useState(1);
|
|
11
|
+
const [croppedAreaPixels, setCroppedAreaPixels] = useState(null);
|
|
12
|
+
const onCropChange = (crop) => {
|
|
13
|
+
setCrop(crop);
|
|
14
|
+
};
|
|
15
|
+
const onZoomChange = (zoom) => {
|
|
16
|
+
setZoom(zoom);
|
|
17
|
+
};
|
|
18
|
+
const onCropCompleteCallback = useCallback((_, croppedAreaPixels) => {
|
|
19
|
+
setCroppedAreaPixels(croppedAreaPixels);
|
|
20
|
+
}, []);
|
|
21
|
+
const createCroppedImage = async () => {
|
|
22
|
+
if (!croppedAreaPixels || !image)
|
|
23
|
+
return;
|
|
24
|
+
const img = new Image();
|
|
25
|
+
img.src = image;
|
|
26
|
+
await new Promise((resolve) => {
|
|
27
|
+
img.onload = resolve;
|
|
28
|
+
});
|
|
29
|
+
const canvas = document.createElement("canvas");
|
|
30
|
+
const ctx = canvas.getContext("2d");
|
|
31
|
+
if (!ctx)
|
|
32
|
+
return;
|
|
33
|
+
canvas.width = croppedAreaPixels.width;
|
|
34
|
+
canvas.height = croppedAreaPixels.height;
|
|
35
|
+
ctx.drawImage(img, croppedAreaPixels.x, croppedAreaPixels.y, croppedAreaPixels.width, croppedAreaPixels.height, 0, 0, croppedAreaPixels.width, croppedAreaPixels.height);
|
|
36
|
+
canvas.toBlob((blob) => {
|
|
37
|
+
if (blob) {
|
|
38
|
+
onCropComplete(blob);
|
|
39
|
+
}
|
|
40
|
+
}, "image/jpeg");
|
|
41
|
+
};
|
|
42
|
+
return (_jsx(Dialog, { open: open, onOpenChange: (isOpen) => !isOpen && onCancel(), children: _jsxs(DialogContent, { className: "sm:max-w-[500px] z-[300]", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Crop Profile Picture" }) }), _jsx("div", { className: "relative h-[300px] w-full bg-gray-100 rounded-md overflow-hidden", children: _jsx(Cropper, { image: image, crop: crop, zoom: zoom, aspect: 1, cropShape: "round", showGrid: false, onCropChange: onCropChange, onCropComplete: onCropCompleteCallback, onZoomChange: onZoomChange }) }), _jsx("div", { className: "py-4", children: _jsxs("div", { className: "flex items-center gap-4", children: [_jsx("span", { className: "text-sm font-medium", children: "Zoom" }), _jsx(Slider, { value: [zoom], min: 1, max: 5, step: 0.1, onValueChange: (values) => { var _a; return setZoom((_a = values[0]) !== null && _a !== void 0 ? _a : 1); }, className: "flex-1" })] }) }), _jsxs(DialogFooter, { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", onClick: onCancel, children: "Cancel" }), _jsx(Button, { onClick: createCroppedImage, children: "Set Profile Picture" })] })] }) }));
|
|
43
|
+
};
|
|
44
|
+
export default ImageCropper;
|
package/dist/misc/input.js
CHANGED
|
@@ -1,29 +1,6 @@
|
|
|
1
|
-
var __assign = (this && this.__assign) || function () {
|
|
2
|
-
__assign = Object.assign || function(t) {
|
|
3
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
-
s = arguments[i];
|
|
5
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
-
t[p] = s[p];
|
|
7
|
-
}
|
|
8
|
-
return t;
|
|
9
|
-
};
|
|
10
|
-
return __assign.apply(this, arguments);
|
|
11
|
-
};
|
|
12
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
13
|
-
var t = {};
|
|
14
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
15
|
-
t[p] = s[p];
|
|
16
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
17
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
18
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
19
|
-
t[p[i]] = s[p[i]];
|
|
20
|
-
}
|
|
21
|
-
return t;
|
|
22
|
-
};
|
|
23
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
2
|
import { cn } from "@myrjfa/state/dist/lib/utils";
|
|
25
|
-
function Input(
|
|
26
|
-
|
|
27
|
-
return (_jsx("input", __assign({ type: type, "data-slot": "input", className: cn("border-input file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className) }, props)));
|
|
3
|
+
function Input({ className, type, ...props }) {
|
|
4
|
+
return (_jsx("input", { type: type, "data-slot": "input", className: cn("border-input file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className), ...props }));
|
|
28
5
|
}
|
|
29
6
|
export { Input };
|
package/dist/misc/label.js
CHANGED
|
@@ -1,31 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
14
|
-
var t = {};
|
|
15
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
16
|
-
t[p] = s[p];
|
|
17
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
18
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
19
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
20
|
-
t[p[i]] = s[p[i]];
|
|
21
|
-
}
|
|
22
|
-
return t;
|
|
23
|
-
};
|
|
24
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
25
3
|
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
26
4
|
import { cn } from "@myrjfa/state/dist/lib/utils";
|
|
27
|
-
function Label(
|
|
28
|
-
|
|
29
|
-
return (_jsx(LabelPrimitive.Root, __assign({ "data-slot": "label", className: cn("flex items-center gap-2 leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className) }, props)));
|
|
5
|
+
function Label({ className, ...props }) {
|
|
6
|
+
return (_jsx(LabelPrimitive.Root, { "data-slot": "label", className: cn("flex items-center gap-2 leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className), ...props }));
|
|
30
7
|
}
|
|
31
8
|
export { Label };
|
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
2
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
3
|
-
if (ar || !(i in from)) {
|
|
4
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
5
|
-
ar[i] = from[i];
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
9
|
-
};
|
|
10
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
export default function LineCarousel(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return (_jsxs("section", { className: "relative w-full pt-10 pb-5 bg-background text-white", children: [_jsx("h2", { className: "text-2xl font-bold text-left mx-10 md:mx-15 lg:mx-25 tracking-tight text-foreground", children: "Popular Skills Offered" }), _jsx("p", { className: "text-muted-foreground mx-10 md:mx-15 lg:mx-25 mb-10", children: "Discover In-Demand Creative Skills for the Modern World." }), _jsxs("div", { className: "relative w-full overflow-hidden", children: [_jsx("div", { className: "absolute inset-y-0 left-0 w-1/4 bg-gradient-to-r from-background to-transparent z-10" }), _jsx("div", { className: "absolute inset-y-0 right-0 w-1/4 bg-gradient-to-l from-background to-transparent z-10" }), _jsx("div", { className: "flex animate-scroll items-center space-x-10", children: loopedSkills.map(function (item, i) { return (_jsxs("div", { className: "flex items-center space-x-3 px-5 text-lg", children: [_jsx(item.icon, { className: "w-6 h-6 text-foreground" }), _jsx("span", { className: "text-muted-foreground font-semibold", children: item.title })] }, i)); }) })] })] }));
|
|
2
|
+
export default function LineCarousel({ skillsData }) {
|
|
3
|
+
const loopedSkills = [...skillsData, ...skillsData, ...skillsData];
|
|
4
|
+
return (_jsxs("section", { className: "relative w-full pt-10 pb-5 bg-background text-white", children: [_jsx("h2", { className: "text-2xl font-bold text-left mx-10 md:mx-15 lg:mx-25 tracking-tight text-foreground", children: "Popular Skills Offered" }), _jsx("p", { className: "text-muted-foreground mx-10 md:mx-15 lg:mx-25 mb-10", children: "Discover In-Demand Creative Skills for the Modern World." }), _jsxs("div", { className: "relative w-full overflow-hidden", children: [_jsx("div", { className: "absolute inset-y-0 left-0 w-1/4 bg-gradient-to-r from-background to-transparent z-10" }), _jsx("div", { className: "absolute inset-y-0 right-0 w-1/4 bg-gradient-to-l from-background to-transparent z-10" }), _jsx("div", { className: "flex animate-scroll items-center space-x-10", children: loopedSkills.map((item, i) => (_jsxs("div", { className: "flex items-center space-x-3 px-5 text-lg", children: [_jsx(item.icon, { className: "w-6 h-6 text-foreground" }), _jsx("span", { className: "text-muted-foreground font-semibold", children: item.title })] }, i))) })] })] }));
|
|
15
5
|
}
|
|
@@ -5,7 +5,6 @@ import { Input } from "./input";
|
|
|
5
5
|
import { Card, CardHeader, CardTitle, CardContent } from "./card";
|
|
6
6
|
import { Trash2, Upload } from "lucide-react";
|
|
7
7
|
import Image from "next/image";
|
|
8
|
-
export default function MultiImageUploader(
|
|
9
|
-
|
|
10
|
-
return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs(CardTitle, { children: ["Images", _jsx(FormDescription, { children: message })] }) }), _jsxs(CardContent, { children: [_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-4", children: [previewImages.map(function (image, index) { return (_jsxs("div", { className: "relative rounded-lg overflow-hidden h-40", children: [_jsx(Image, { id: "image-" + index, src: image, alt: "Opportunity image ".concat(index + 1), fill: true, className: "object-cover" }), _jsx(Button, { type: "button", onClick: function () { return handleRemoveImage(index); }, className: "absolute top-2 right-2 bg-white/80 rounded-full hover:bg-white", children: _jsx(Trash2, { className: "text-red-500" }) })] }, index)); }), _jsxs("div", { className: "flex flex-col items-center justify-center w-full space-y-4", children: [_jsx("label", { htmlFor: "image", className: "cursor-pointer w-full", children: _jsxs("div", { className: "border-2 border-dashed border-slate-300 rounded-lg p-6 flex flex-col items-center justify-center text-slate-500 hover:border-primary hover:text-primary transition-colors", children: [_jsx(Upload, { className: "h-12 w-12 text-gray-500 mb-4" }), _jsx("span", { className: "text-lg font-semibold mb-2", children: "Upload Image" }), _jsx("span", { className: "text-sm", children: "Click or drag to upload" })] }) }), _jsx(Input, { id: "image", type: "file", accept: "image/*", multiple: true, onChange: handleImageUpload, placeholder: "Upload Image", className: "hidden" })] })] }), _jsx(FormDescription, { children: "Images should be in Valid format. Maximum file size: 5MB." })] })] }));
|
|
8
|
+
export default function MultiImageUploader({ previewImages, handleImageUpload, handleRemoveImage, message }) {
|
|
9
|
+
return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs(CardTitle, { children: ["Images", _jsx(FormDescription, { children: message })] }) }), _jsxs(CardContent, { children: [_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-4", children: [previewImages.map((image, index) => (_jsxs("div", { className: "relative rounded-lg overflow-hidden h-40", children: [_jsx(Image, { id: "image-" + index, src: image, alt: `Opportunity image ${index + 1}`, fill: true, className: "object-cover" }), _jsx(Button, { type: "button", onClick: () => handleRemoveImage(index), className: "absolute top-2 right-2 bg-white/80 rounded-full hover:bg-white", children: _jsx(Trash2, { className: "text-red-500" }) })] }, index))), _jsxs("div", { className: "flex flex-col items-center justify-center w-full space-y-4", children: [_jsx("label", { htmlFor: "image", className: "cursor-pointer w-full", children: _jsxs("div", { className: "border-2 border-dashed border-slate-300 rounded-lg p-6 flex flex-col items-center justify-center text-slate-500 hover:border-primary hover:text-primary transition-colors", children: [_jsx(Upload, { className: "h-12 w-12 text-gray-500 mb-4" }), _jsx("span", { className: "text-lg font-semibold mb-2", children: "Upload Image" }), _jsx("span", { className: "text-sm", children: "Click or drag to upload" })] }) }), _jsx(Input, { id: "image", type: "file", accept: "image/*", multiple: true, onChange: handleImageUpload, placeholder: "Upload Image", className: "hidden" })] })] }), _jsx(FormDescription, { children: "Images should be in Valid format. Maximum file size: 5MB." })] })] }));
|
|
11
10
|
}
|
package/dist/misc/newsLetter.js
CHANGED
|
@@ -1,51 +1,4 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
50
3
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
51
4
|
import { subscribeToNewsLetter } from "@myrjfa/state/dist/lib/actions";
|
|
@@ -57,45 +10,32 @@ import { showAlert } from "./alertdialogclaude";
|
|
|
57
10
|
import { Button } from "./button";
|
|
58
11
|
import { Form, FormControl, FormField, FormItem, FormMessage } from "./form";
|
|
59
12
|
import { Input } from "./input";
|
|
60
|
-
|
|
13
|
+
const formSchema = z.object({
|
|
61
14
|
email: z.string().email("Please enter a valid email address"),
|
|
62
15
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
16
|
+
const NewsletterSubscribe = () => {
|
|
17
|
+
const pathname = usePathname();
|
|
18
|
+
const form = useForm({
|
|
66
19
|
resolver: zodResolver(formSchema),
|
|
67
20
|
defaultValues: {
|
|
68
21
|
email: "",
|
|
69
22
|
},
|
|
70
23
|
});
|
|
71
|
-
useEffect(
|
|
24
|
+
useEffect(() => {
|
|
72
25
|
form.reset();
|
|
73
26
|
}, [pathname]);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
form.setValue("email", "");
|
|
88
|
-
return [4 /*yield*/, showAlert(res.message || "Subscribed successfully!")];
|
|
89
|
-
case 3:
|
|
90
|
-
_a.sent();
|
|
91
|
-
_a.label = 4;
|
|
92
|
-
case 4: return [2 /*return*/];
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}); };
|
|
96
|
-
return (_jsx(Form, __assign({}, form, { children: _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), noValidate: true, className: "mt-4 flex flex-col sm:flex-row gap-3", children: [_jsx(FormField, { control: form.control, name: "email", render: function (_a) {
|
|
97
|
-
var field = _a.field;
|
|
98
|
-
return (_jsxs(FormItem, { className: "flex-1", children: [_jsx(FormControl, { children: _jsx(Input, __assign({ placeholder: "Your email address", type: "email", disabled: isSubmitting }, field)) }), _jsx(FormMessage, {})] }));
|
|
99
|
-
} }), _jsx(Button, { type: "submit", disabled: isSubmitting, className: "w-full sm:w-auto", children: isSubmitting ? "Subscribing..." : "Subscribe" })] }) })));
|
|
27
|
+
const { isSubmitting } = form.formState;
|
|
28
|
+
const onSubmit = async (values) => {
|
|
29
|
+
const res = await subscribeToNewsLetter(values.email);
|
|
30
|
+
if (res === null || res === void 0 ? void 0 : res.error) {
|
|
31
|
+
form.setError("email", { message: res.error });
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
form.reset();
|
|
35
|
+
form.setValue("email", "");
|
|
36
|
+
await showAlert(res.message || "Subscribed successfully!");
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
return (_jsx(Form, { ...form, children: _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), noValidate: true, className: "mt-4 flex flex-col sm:flex-row gap-3", children: [_jsx(FormField, { control: form.control, name: "email", render: ({ field }) => (_jsxs(FormItem, { className: "flex-1", children: [_jsx(FormControl, { children: _jsx(Input, { placeholder: "Your email address", type: "email", disabled: isSubmitting, ...field }) }), _jsx(FormMessage, {})] })) }), _jsx(Button, { type: "submit", disabled: isSubmitting, className: "w-full sm:w-auto", children: isSubmitting ? "Subscribing..." : "Subscribe" })] }) }));
|
|
100
40
|
};
|
|
101
41
|
export default NewsletterSubscribe;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export declare function NotificationBell({
|
|
2
|
-
id: string | null;
|
|
1
|
+
export declare function NotificationBell({ navItemColor }: {
|
|
3
2
|
navItemColor: string;
|
|
4
3
|
}): import("react/jsx-runtime").JSX.Element;
|
|
5
4
|
export declare function MobileNotificationBell(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/misc/notification.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/misc/notification.tsx"],"names":[],"mappings":"AAkDA,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,EAAE;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,2CA8I1E;AAED,wBAAgB,sBAAsB,4CAUrC"}
|
|
@@ -1,56 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
50
3
|
import { Popover, PopoverContent, PopoverTrigger } from "@radix-ui/react-popover";
|
|
51
|
-
import { toggleAllNotification, toggleNotification } from "@myrjfa/state/dist/lib/actions";
|
|
4
|
+
import { getNotifications, toggleAllNotification, toggleNotification } from "@myrjfa/state/dist/lib/actions";
|
|
52
5
|
import { formatTimestamp } from "@myrjfa/state/dist/lib/utils";
|
|
53
|
-
import { Bell } from "lucide-react";
|
|
6
|
+
import { Bell, MessageCircle, CheckCircle2, Receipt, Users, AlertCircle, Megaphone, Briefcase, ShieldCheck, ShieldX, Package, ClipboardList } from "lucide-react";
|
|
54
7
|
import { useRouter } from "next/navigation";
|
|
55
8
|
import { useEffect, useState } from "react";
|
|
56
9
|
import { FaSpinner } from "react-icons/fa6";
|
|
@@ -59,89 +12,100 @@ import { Button } from "./button";
|
|
|
59
12
|
import { Card, CardHeader, CardTitle } from "./card";
|
|
60
13
|
import { ScrollArea } from "./scroll-area";
|
|
61
14
|
import { MobileNavItem } from "../header/mobile-nav-item";
|
|
62
|
-
|
|
63
|
-
|
|
15
|
+
const NOTIF_LIMIT_FOR_BELL = 10;
|
|
16
|
+
const getNotificationIcon = (notif) => {
|
|
17
|
+
const type = notif.type || "general";
|
|
64
18
|
switch (type) {
|
|
65
|
-
case "
|
|
66
|
-
return _jsx(
|
|
19
|
+
case "new_message":
|
|
20
|
+
return _jsx(MessageCircle, { className: "w-4 h-4 text-blue-500 mt-0.5 flex-shrink-0" });
|
|
21
|
+
case "milestone_completed":
|
|
22
|
+
return _jsx(CheckCircle2, { className: "w-4 h-4 text-green-500 mt-0.5 flex-shrink-0" });
|
|
23
|
+
case "expense_added":
|
|
24
|
+
return _jsx(Receipt, { className: "w-4 h-4 text-orange-500 mt-0.5 flex-shrink-0" });
|
|
25
|
+
case "group_invite":
|
|
26
|
+
return _jsx(Users, { className: "w-4 h-4 text-purple-500 mt-0.5 flex-shrink-0" });
|
|
27
|
+
case "mention":
|
|
28
|
+
return _jsx(Megaphone, { className: "w-4 h-4 text-yellow-500 mt-0.5 flex-shrink-0" });
|
|
29
|
+
case "application_received":
|
|
30
|
+
case "application_status":
|
|
31
|
+
case "application_shortlisted":
|
|
32
|
+
return _jsx(Briefcase, { className: "w-4 h-4 text-indigo-500 mt-0.5 flex-shrink-0" });
|
|
33
|
+
case "id_verified":
|
|
34
|
+
return _jsx(ShieldCheck, { className: "w-4 h-4 text-emerald-500 mt-0.5 flex-shrink-0" });
|
|
35
|
+
case "id_rejected":
|
|
36
|
+
return _jsx(ShieldX, { className: "w-4 h-4 text-red-500 mt-0.5 flex-shrink-0" });
|
|
37
|
+
case "package_enquiry":
|
|
38
|
+
return _jsx(Package, { className: "w-4 h-4 text-cyan-500 mt-0.5 flex-shrink-0" });
|
|
39
|
+
case "opportunity_assigned":
|
|
40
|
+
return _jsx(ClipboardList, { className: "w-4 h-4 text-amber-500 mt-0.5 flex-shrink-0" });
|
|
41
|
+
case "system":
|
|
42
|
+
return _jsx(AlertCircle, { className: "w-4 h-4 text-gray-500 mt-0.5 flex-shrink-0" });
|
|
67
43
|
default:
|
|
68
|
-
return _jsx("div", { className:
|
|
44
|
+
return _jsx("div", { className: `w-2.5 h-2.5 rounded-full mt-1.5 flex-shrink-0 ${!notif.read ? "bg-blue-500" : "bg-gray-300"}` });
|
|
69
45
|
}
|
|
70
46
|
};
|
|
71
|
-
export function NotificationBell(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return [2 /*return*/];
|
|
84
|
-
});
|
|
85
|
-
}); };
|
|
86
|
-
fetchData();
|
|
87
|
-
}, [id]);
|
|
88
|
-
var handleMarkAllNotifRead = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
89
|
-
var response;
|
|
90
|
-
return __generator(this, function (_a) {
|
|
91
|
-
switch (_a.label) {
|
|
92
|
-
case 0: return [4 /*yield*/, toggleAllNotification(true)];
|
|
93
|
-
case 1:
|
|
94
|
-
response = _a.sent();
|
|
95
|
-
if (!(response === null || response === void 0 ? void 0 : response.error)) return [3 /*break*/, 3];
|
|
96
|
-
return [4 /*yield*/, showAlert(response.error)];
|
|
97
|
-
case 2:
|
|
98
|
-
_a.sent();
|
|
99
|
-
return [3 /*break*/, 4];
|
|
100
|
-
case 3:
|
|
101
|
-
setNotifs(notifs.map(function (notif) { return (__assign(__assign({}, notif), { read: true })); }));
|
|
102
|
-
setUnreadCount(0);
|
|
103
|
-
console.log("marked");
|
|
104
|
-
_a.label = 4;
|
|
105
|
-
case 4: return [2 /*return*/];
|
|
47
|
+
export function NotificationBell({ navItemColor }) {
|
|
48
|
+
const [notifs, setNotifs] = useState([]);
|
|
49
|
+
const [unreadCount, setUnreadCount] = useState(0);
|
|
50
|
+
const [loadingNotifId, setLoadingNotifId] = useState(null);
|
|
51
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
52
|
+
const router = useRouter();
|
|
53
|
+
const fetchData = async () => {
|
|
54
|
+
try {
|
|
55
|
+
const response = await getNotifications(NOTIF_LIMIT_FOR_BELL);
|
|
56
|
+
if (response && !response.error) {
|
|
57
|
+
setNotifs(response.notifs || []);
|
|
58
|
+
setUnreadCount(response.unreadCount || 0);
|
|
106
59
|
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
console.error("Failed to fetch notifications:", err);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
// Re-fetch when popover opens
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (isOpen)
|
|
68
|
+
fetchData();
|
|
69
|
+
}, [isOpen]);
|
|
70
|
+
const handleMarkAllNotifRead = async () => {
|
|
71
|
+
const response = await toggleAllNotification(true);
|
|
72
|
+
if (response === null || response === void 0 ? void 0 : response.error) {
|
|
73
|
+
await showAlert(response.error);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
setNotifs(notifs.map((notif) => ({
|
|
77
|
+
...notif, read: true
|
|
78
|
+
})));
|
|
79
|
+
setUnreadCount(0);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const handleNotifClick = async (notif) => {
|
|
83
|
+
if (loadingNotifId)
|
|
84
|
+
return;
|
|
85
|
+
if (!notif.read) {
|
|
86
|
+
setLoadingNotifId(notif._id);
|
|
87
|
+
const response = await toggleNotification(notif._id, true);
|
|
88
|
+
if (response === null || response === void 0 ? void 0 : response.error) {
|
|
89
|
+
await showAlert(response.error);
|
|
137
90
|
}
|
|
138
|
-
|
|
139
|
-
|
|
91
|
+
else {
|
|
92
|
+
setNotifs(notifs.map((n) => n._id === notif._id ? { ...n, read: true } : n));
|
|
93
|
+
setUnreadCount(Math.max(0, unreadCount - 1));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
setLoadingNotifId(null);
|
|
97
|
+
// Navigate to the link or URL
|
|
98
|
+
const url = notif.link;
|
|
99
|
+
if (url) {
|
|
100
|
+
setIsOpen(false);
|
|
101
|
+
router.push(url);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
140
104
|
if (notifs == null)
|
|
141
|
-
return _jsx(FaSpinner, {});
|
|
142
|
-
return _jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("div", { className:
|
|
143
|
-
|
|
144
|
-
|
|
105
|
+
return _jsx(FaSpinner, { className: "animate-spin" });
|
|
106
|
+
return _jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("div", { className: `relative cursor-pointer ${navItemColor} transition-colors`, "aria-label": "Notification Bell", children: [_jsx(Bell, { className: "h-5 w-5" }), unreadCount > 0 && (_jsx("span", { className: "absolute -top-1.5 -right-1.5 flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold text-white animate-pulse", children: unreadCount > 99 ? "99+" : unreadCount }))] }) }), _jsx(PopoverContent, { className: "w-96 p-0 mt-3 bg-white dark:bg-gray-900 rounded-xl shadow-xl border border-gray-100 dark:border-gray-800", align: "end", sideOffset: 5, children: _jsxs(Card, { className: "border-0 shadow-none bg-transparent", children: [_jsx(CardHeader, { className: "px-5 pb-2", children: _jsxs("div", { className: "flex justify-between items-center", children: [_jsx(CardTitle, { className: "text-base font-semibold", children: "Notifications" }), notifs.length > 0 && unreadCount > 0 && (_jsx(Button, { variant: "ghost", size: "sm", className: "text-xs text-teal-600 hover:text-teal-800 dark:text-teal-400", onClick: handleMarkAllNotifRead, children: "Mark all as read" }))] }) }), _jsx(ScrollArea, { className: "h-80 w-full", children: _jsx("div", { className: "px-2 pb-2", children: notifs.length === 0 ? (_jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-gray-400", children: [_jsx(Bell, { className: "w-10 h-10 mb-3 opacity-30" }), _jsx("p", { className: "text-sm", children: "You're all caught up \uD83C\uDF89" })] })) : (notifs.map((notif) => (_jsxs("div", { className: `flex items-start gap-3 p-3 rounded-lg cursor-pointer transition-all duration-200 hover:bg-gray-50 dark:hover:bg-gray-800/50 ${!notif.read
|
|
107
|
+
? "bg-teal-50/50 dark:bg-teal-900/10 border-l-2 border-teal-500"
|
|
108
|
+
: "border-l-2 border-transparent"} ${loadingNotifId === notif._id ? "opacity-50 pointer-events-none" : ""}`, onClick: () => handleNotifClick(notif), children: [_jsx("div", { className: "flex-shrink-0 mt-0.5", children: getNotificationIcon(notif) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("p", { className: `text-sm leading-snug ${!notif.read ? "font-medium text-gray-900 dark:text-white" : "text-gray-600 dark:text-gray-400"}`, children: notif.message }), _jsxs("div", { className: "flex items-center gap-2 mt-1", children: [_jsx("p", { className: "text-[11px] text-gray-400", children: notif.timestamp ? formatTimestamp(notif.timestamp) : "" }), notif.type && notif.type !== "general" && (_jsx("span", { className: "text-[10px] px-1.5 py-0.5 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400", children: notif.type.replace(/_/g, " ") }))] })] }), !notif.read && (_jsx("div", { className: "flex-shrink-0 mt-2", children: _jsx("div", { className: "w-2 h-2 rounded-full bg-teal-500" }) }))] }, notif._id)))) }) }), notifs.length > NOTIF_LIMIT_FOR_BELL && (_jsx("div", { className: "px-3 py-2 border-t border-gray-100 dark:border-gray-800", children: _jsx(Button, { variant: "ghost", className: "w-full text-teal-600 hover:text-teal-800 hover:bg-teal-50 dark:text-teal-400 dark:hover:bg-teal-900/20 text-sm", onClick: () => { setIsOpen(false); router.push("/inbox"); }, children: "View all notifications" }) }))] }) })] });
|
|
145
109
|
}
|
|
146
110
|
export function MobileNotificationBell() {
|
|
147
111
|
return (_jsx(MobileNavItem, { icon: _jsx("div", { className: "relative", children: _jsx(Bell, { className: "h-5 w-5" }) }), label: "Notifications", href: "/inbox" }));
|