|
1 | | -import { ChevronDown, ChevronRight, PlusSquare } from "lucide-react"; |
| 1 | +import { ChevronDown, ChevronRight, PlusSquare, XIcon } from "lucide-react"; |
2 | 2 | import * as RadioGroup from "@radix-ui/react-radio-group"; |
3 | 3 | import { useEffect, useRef, useState, type CSSProperties } from "react"; |
4 | 4 | import { useConfirm, useToastContext } from "~/Providers"; |
5 | 5 | import { NotificationSeverity } from "~/common"; |
6 | 6 | import { |
7 | 7 | Sheet, |
| 8 | + SheetClose, |
8 | 9 | SheetContent, |
9 | 10 | SheetHeader, |
10 | 11 | SheetTitle, |
@@ -199,40 +200,48 @@ export function CreateChannelDrawer({ |
199 | 200 | <Sheet open={open} onOpenChange={handleClose}> |
200 | 201 | <SheetContent |
201 | 202 | side="right" |
202 | | - className="w-full max-w-[900px] sm:max-w-[1000px] overflow-y-auto scroll-on-scroll bg-white pl-20 pr-20 flex flex-col" |
203 | | - onScroll={handleBodyScroll} |
204 | | - data-scrolling={isBodyScrolling ? "true" : "false"} |
| 203 | + hideClose |
| 204 | + className="w-full max-w-[900px] sm:max-w-[1000px] overflow-hidden bg-white pl-20 pr-20 flex flex-col" |
205 | 205 | > |
206 | | - <SheetHeader className="sticky top-0 z-10 ml-6 mr-6 pt-6 pb-4 border-b border-[#E5E6EB] bg-white"> |
207 | | - <SheetTitle className="text-[16px] -ml-4 font-medium text-[#1D2129]"> |
208 | | - {isEditMode ? localize("com_subscription.channel_settings") : localize("com_subscription.create_channel")} |
209 | | - </SheetTitle> |
210 | | - </SheetHeader> |
| 206 | + <SheetClose className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 z-20 rounded-xs opacity-70 transition-opacity hover:opacity-100 disabled:pointer-events-none"> |
| 207 | + <XIcon className="size-4" /> |
| 208 | + <span className="sr-only">Close</span> |
| 209 | + </SheetClose> |
| 210 | + <div |
| 211 | + className="min-h-0 flex-1 overflow-y-auto scroll-on-scroll" |
| 212 | + onScroll={handleBodyScroll} |
| 213 | + data-scrolling={isBodyScrolling ? "true" : "false"} |
| 214 | + > |
| 215 | + <SheetHeader className="sticky top-0 z-10 ml-6 mr-6 pt-6 pb-4 border-b border-[#E5E6EB] bg-white"> |
| 216 | + <SheetTitle className="text-[16px] -ml-4 font-medium text-[#1D2129]"> |
| 217 | + {isEditMode ? localize("com_subscription.channel_settings") : localize("com_subscription.create_channel")} |
| 218 | + </SheetTitle> |
| 219 | + </SheetHeader> |
211 | 220 |
|
212 | | - {form.showSuccess && !isEditMode ? ( |
213 | | - <CreateChannelSuccessContent |
214 | | - onViewChannel={() => { |
215 | | - if (form.createdChannelId) { |
216 | | - onViewChannel?.(form.createdChannelId); |
217 | | - } |
218 | | - form.resetForm(); |
219 | | - }} |
220 | | - onManageMembers={() => { |
221 | | - if (form.createdChannelId) { |
222 | | - onManageMembers?.(form.createdChannelId); |
223 | | - onViewChannel?.(form.createdChannelId); |
| 221 | + {form.showSuccess && !isEditMode ? ( |
| 222 | + <CreateChannelSuccessContent |
| 223 | + onViewChannel={() => { |
| 224 | + if (form.createdChannelId) { |
| 225 | + onViewChannel?.(form.createdChannelId); |
| 226 | + } |
| 227 | + form.resetForm(); |
| 228 | + }} |
| 229 | + onManageMembers={() => { |
| 230 | + if (form.createdChannelId) { |
| 231 | + onManageMembers?.(form.createdChannelId); |
| 232 | + onViewChannel?.(form.createdChannelId); |
224 | 233 |
|
225 | | - } |
226 | | - form.resetForm(); |
227 | | - onOpenChange(false); |
228 | | - }} |
229 | | - /> |
230 | | - ) : ( |
231 | | - <div |
232 | | - className={cn( |
233 | | - "overflow-visible px-6 py-5 space-y-5" |
234 | | - )} |
235 | | - > |
| 234 | + } |
| 235 | + form.resetForm(); |
| 236 | + onOpenChange(false); |
| 237 | + }} |
| 238 | + /> |
| 239 | + ) : ( |
| 240 | + <div |
| 241 | + className={cn( |
| 242 | + "overflow-visible px-6 py-5 space-y-5" |
| 243 | + )} |
| 244 | + > |
236 | 245 | {/* 添加信息源 */} |
237 | 246 | <div className="space-y-2"> |
238 | 247 | <Label className="text-[14px] text-[#1D2129]"> |
@@ -596,82 +605,83 @@ export function CreateChannelDrawer({ |
596 | 605 | </div> |
597 | 606 | )} |
598 | 607 | </div> |
599 | | - </div> |
600 | | - )} |
| 608 | + </div> |
| 609 | + )} |
601 | 610 |
|
602 | | - {/* 底部操作按钮 */} |
603 | | - {(!form.showSuccess || isEditMode) && ( |
604 | | - <div className="sticky bottom-0 z-10 mt-auto flex justify-end gap-3 px-6 pt-10 pb-5 border-t border-[#E5E6EB] bg-white"> |
605 | | - <Button |
606 | | - variant="secondary" |
607 | | - onClick={() => handleClose(false)} |
608 | | - className="h-8 rounded-[6px] px-4 inline-flex items-center justify-center leading-none bg-[#F2F3F5] hover:bg-[#E5E6EB] border-none text-[14px] !font-normal text-[#4E5969]" |
609 | | - > |
610 | | - {localize("cancel")} |
611 | | - </Button> |
612 | | - <Button |
613 | | - disabled={form.submitting} |
614 | | - onClick={async () => { |
615 | | - const data: CreateChannelFormData = { |
616 | | - sources: form.sources, |
617 | | - channelName: form.channelName.trim(), |
618 | | - channelDesc: form.channelDesc.trim(), |
619 | | - visibility: form.visibility, |
620 | | - publishToSquare: form.publishToSquare, |
621 | | - contentFilter: form.contentFilter, |
622 | | - filterGroups: form.filterGroups, |
623 | | - topFilterRelation: form.topFilterRelation, |
624 | | - createSubChannel: form.createSubChannel, |
625 | | - subChannels: form.subChannels |
626 | | - }; |
| 611 | + {/* 底部操作按钮 */} |
| 612 | + {(!form.showSuccess || isEditMode) && ( |
| 613 | + <div className="sticky bottom-0 z-10 mt-auto flex justify-end gap-3 px-6 pt-10 pb-5 border-t border-[#E5E6EB] bg-white"> |
| 614 | + <Button |
| 615 | + variant="secondary" |
| 616 | + onClick={() => handleClose(false)} |
| 617 | + className="h-8 rounded-[6px] px-4 inline-flex items-center justify-center leading-none bg-[#F2F3F5] hover:bg-[#E5E6EB] border-none text-[14px] !font-normal text-[#4E5969]" |
| 618 | + > |
| 619 | + {localize("cancel")} |
| 620 | + </Button> |
| 621 | + <Button |
| 622 | + disabled={form.submitting} |
| 623 | + onClick={async () => { |
| 624 | + const data: CreateChannelFormData = { |
| 625 | + sources: form.sources, |
| 626 | + channelName: form.channelName.trim(), |
| 627 | + channelDesc: form.channelDesc.trim(), |
| 628 | + visibility: form.visibility, |
| 629 | + publishToSquare: form.publishToSquare, |
| 630 | + contentFilter: form.contentFilter, |
| 631 | + filterGroups: form.filterGroups, |
| 632 | + topFilterRelation: form.topFilterRelation, |
| 633 | + createSubChannel: form.createSubChannel, |
| 634 | + subChannels: form.subChannels |
| 635 | + }; |
627 | 636 |
|
628 | | - // 创建和编辑统一走同一套校验逻辑: |
629 | | - // 1) 至少 1 个信息源 |
630 | | - // 2) 频道名称不能为空 |
631 | | - // 3) 主频道 / 子频道筛选条件中的关键词不能为空 |
632 | | - const validationError = validateCreateChannelForm(data, localize); |
633 | | - if (validationError) { |
634 | | - showToast({ |
635 | | - message: validationError, |
636 | | - severity: NotificationSeverity.WARNING |
637 | | - }); |
638 | | - return; |
639 | | - } |
| 637 | + // 创建和编辑统一走同一套校验逻辑: |
| 638 | + // 1) 至少 1 个信息源 |
| 639 | + // 2) 频道名称不能为空 |
| 640 | + // 3) 主频道 / 子频道筛选条件中的关键词不能为空 |
| 641 | + const validationError = validateCreateChannelForm(data, localize); |
| 642 | + if (validationError) { |
| 643 | + showToast({ |
| 644 | + message: validationError, |
| 645 | + severity: NotificationSeverity.WARNING |
| 646 | + }); |
| 647 | + return; |
| 648 | + } |
640 | 649 |
|
641 | | - if (!onConfirm) return; |
642 | | - try { |
643 | | - form.setSubmitting(true); |
644 | | - const res = await onConfirm(data); |
645 | | - if (!isEditMode) { |
646 | | - form.setCreatedChannelId(res.channelId); |
647 | | - form.setShowSuccess(true); |
648 | | - } else { |
| 650 | + if (!onConfirm) return; |
| 651 | + try { |
| 652 | + form.setSubmitting(true); |
| 653 | + const res = await onConfirm(data); |
| 654 | + if (!isEditMode) { |
| 655 | + form.setCreatedChannelId(res.channelId); |
| 656 | + form.setShowSuccess(true); |
| 657 | + } else { |
| 658 | + showToast({ |
| 659 | + message: localize("com_subscription.save_success"), |
| 660 | + severity: NotificationSeverity.SUCCESS |
| 661 | + }); |
| 662 | + form.resetForm(); |
| 663 | + onOpenChange(false); |
| 664 | + } |
| 665 | + } catch { |
649 | 666 | showToast({ |
650 | | - message: localize("com_subscription.save_success"), |
651 | | - severity: NotificationSeverity.SUCCESS |
| 667 | + message: localize("channel_create_failed") || localize("com_subscription.create_channel_failed_retry"), |
| 668 | + severity: NotificationSeverity.ERROR |
652 | 669 | }); |
653 | | - form.resetForm(); |
654 | | - onOpenChange(false); |
| 670 | + } finally { |
| 671 | + form.setSubmitting(false); |
655 | 672 | } |
656 | | - } catch { |
657 | | - showToast({ |
658 | | - message: localize("channel_create_failed") || localize("com_subscription.create_channel_failed_retry"), |
659 | | - severity: NotificationSeverity.ERROR |
660 | | - }); |
661 | | - } finally { |
662 | | - form.setSubmitting(false); |
663 | | - } |
664 | | - }} |
665 | | - className="h-8 rounded-[6px] px-4 inline-flex items-center justify-center leading-none bg-[#165DFF] hover:bg-[#4080FF] text-white border-none text-[14px] !font-normal disabled:opacity-50" |
666 | | - > |
667 | | - {isEditMode |
668 | | - ? form.submitting ? localize("com_subscription.saving") : localize("com_subscription.save") |
669 | | - : form.submitting |
670 | | - ? (localize("creating") || localize("com_subscription.creating")) |
671 | | - : (localize("com_subscription.confirm_creation") || localize("com_subscription.confirm_create"))} |
672 | | - </Button> |
673 | | - </div> |
674 | | - )} |
| 673 | + }} |
| 674 | + className="h-8 rounded-[6px] px-4 inline-flex items-center justify-center leading-none bg-[#165DFF] hover:bg-[#4080FF] text-white border-none text-[14px] !font-normal disabled:opacity-50" |
| 675 | + > |
| 676 | + {isEditMode |
| 677 | + ? form.submitting ? localize("com_subscription.saving") : localize("com_subscription.save") |
| 678 | + : form.submitting |
| 679 | + ? (localize("creating") || localize("com_subscription.creating")) |
| 680 | + : (localize("com_subscription.confirm_creation") || localize("com_subscription.confirm_create"))} |
| 681 | + </Button> |
| 682 | + </div> |
| 683 | + )} |
| 684 | + </div> |
675 | 685 | </SheetContent> |
676 | 686 | </Sheet> |
677 | 687 |
|
|
0 commit comments