@c-rex/components 0.0.12 → 0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c-rex/components",
3
- "version": "0.0.12",
3
+ "version": "0.1.1",
4
4
  "files": [
5
5
  "src"
6
6
  ],
@@ -52,6 +52,10 @@
52
52
  "./sidebar": {
53
53
  "types": "./src/sidebar.tsx",
54
54
  "import": "./src/sidebar.tsx"
55
+ },
56
+ "./dialog-filter": {
57
+ "types": "./src/dialog-filter.tsx",
58
+ "import": "./src/dialog-filter.tsx"
55
59
  }
56
60
  },
57
61
  "scripts": {
@@ -82,14 +86,18 @@
82
86
  "typescript": "latest"
83
87
  },
84
88
  "dependencies": {
89
+ "@c-rex/config": "*",
90
+ "@c-rex/constants": "*",
85
91
  "@c-rex/contexts": "*",
86
92
  "@c-rex/interfaces": "*",
87
93
  "@c-rex/services": "*",
88
94
  "@c-rex/ui": "*",
89
95
  "@c-rex/utils": "*",
90
- "@c-rex/config": "*",
91
- "@c-rex/constants": "*",
96
+ "country-flag-icons": "^1.5.19",
97
+ "lucide-react": "^0.511.0",
92
98
  "next": "^14",
99
+ "next-intl": "^4.1.0",
100
+ "nuqs": "^2.4.3",
93
101
  "react": "^18",
94
102
  "react-dom": "^18",
95
103
  "tailwindcss-animate": "^1.0.7"
@@ -1,3 +1,4 @@
1
+ import React from "react";
1
2
  import { Command as CommandPrimitive } from "cmdk";
2
3
  import { Check } from "lucide-react";
3
4
  import { useEffect, useState } from "react";
@@ -28,7 +29,6 @@ export const AutoComplete = ({
28
29
  }: Props) => {
29
30
  const [query, setQuery] = useState(initialValue);
30
31
  const [suggestions, setSuggestions] = useState<string[]>([]);
31
-
32
32
  const [open, setOpen] = useState(false);
33
33
 
34
34
  useEffect(() => {
package/src/blog-card.tsx CHANGED
@@ -1,8 +1,7 @@
1
1
  import Link from "next/link";
2
2
  import { cn } from "@c-rex/utils";
3
3
  import { BlurImage } from "./blur-image";
4
-
5
- //import Author from "./author";
4
+ import { useTranslations } from "next-intl";
6
5
 
7
6
  interface BlogCardProp {
8
7
  data: {
@@ -24,6 +23,8 @@ export const BlogCard = ({
24
23
  priority,
25
24
  horizontal = false,
26
25
  }: BlogCardProp) => {
26
+ const t = useTranslations("results")
27
+
27
28
  return (
28
29
  <article
29
30
  className={cn(
@@ -80,7 +81,7 @@ export const BlogCard = ({
80
81
  </div>
81
82
  </div>
82
83
  <Link href={data.slug} className="absolute inset-0" target="_blank">
83
- <span className="sr-only">View Article</span>
84
+ <span className="sr-only">{t("viewArticle")}</span>
84
85
  </Link>
85
86
  </article>
86
87
  );
@@ -1,4 +1,4 @@
1
- import { FC, ReactNode } from "react";
1
+ import React, { FC, Fragment, ReactNode } from "react";
2
2
  import {
3
3
  Breadcrumb as BreadcrumbComponent,
4
4
  BreadcrumbItem,
@@ -9,6 +9,7 @@ import {
9
9
  } from "@c-rex/ui/breadcrumb";
10
10
  import { Skeleton } from "@c-rex/ui/skeleton";
11
11
  import { TreeOfContent } from "@c-rex/interfaces";
12
+ import { useTranslations } from 'next-intl';
12
13
 
13
14
  interface BreadcrumbProps {
14
15
  items: TreeOfContent[];
@@ -16,6 +17,7 @@ interface BreadcrumbProps {
16
17
  }
17
18
 
18
19
  export const Breadcrumb: FC<BreadcrumbProps> = ({ items, loading }) => {
20
+ const t = useTranslations("breadcrumbs");
19
21
  if (!items) {
20
22
  return null;
21
23
  }
@@ -25,7 +27,7 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ items, loading }) => {
25
27
  <BreadcrumbComponent>
26
28
  <BreadcrumbList>
27
29
  <BreadcrumbItem>
28
- <BreadcrumbPage>Home</BreadcrumbPage>
30
+ <BreadcrumbPage>{t("home")}</BreadcrumbPage>
29
31
  </BreadcrumbItem>
30
32
  <BreadcrumbSeparator />
31
33
  <BreadcrumbItem>
@@ -42,7 +44,7 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ items, loading }) => {
42
44
 
43
45
  const homeItem: TreeOfContent = {
44
46
  link: "/",
45
- label: "Home",
47
+ label: t("home"),
46
48
  id: "home",
47
49
  active: false,
48
50
  children: [],
@@ -65,14 +67,14 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ items, loading }) => {
65
67
  const isLast = index === newItemList.length - 1;
66
68
 
67
69
  return (
68
- <>
70
+ <Fragment key={`${item.label}-fragment`}>
69
71
  <BreadcrumbItem key={`${item.label}-item`}>
70
72
  {renderLink(!isLast, item)}
71
73
  </BreadcrumbItem>
72
74
  {!isLast && (
73
75
  <BreadcrumbSeparator key={`${item.label}-separator`} />
74
76
  )}
75
- </>
77
+ </Fragment>
76
78
  );
77
79
  })}
78
80
  </BreadcrumbList>
@@ -0,0 +1,102 @@
1
+ import React, { FC, useState } from "react"
2
+ import { Button } from "@c-rex/ui/button"
3
+ import {
4
+ Dialog,
5
+ DialogClose,
6
+ DialogContent,
7
+ DialogFooter,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ DialogTrigger,
11
+ } from "@c-rex/ui/dialog"
12
+ import { Checkbox } from "@c-rex/ui/checkbox"
13
+ import { Label } from "@c-rex/ui/label"
14
+ import { useQueryState } from "nuqs"
15
+ import { useTranslations } from "next-intl"
16
+
17
+ interface DialogFilterProps {
18
+ trigger: React.ReactNode;
19
+ startSelectedLanguages: string[];
20
+ availableLanguages: any;
21
+ }
22
+
23
+ export const DialogFilter: FC<DialogFilterProps> = ({
24
+ trigger,
25
+ startSelectedLanguages,
26
+ availableLanguages,
27
+ }) => {
28
+ const t = useTranslations();
29
+
30
+ const [_, setContentLanguage] = useQueryState('language', {
31
+ history: 'push',
32
+ shallow: false,
33
+ })
34
+
35
+ const [languages, setLanguages] = useState(availableLanguages.map((item: any) => {
36
+ const checked = startSelectedLanguages.includes(item.value)
37
+ return {
38
+ lang: item.lang,
39
+ value: item.value,
40
+ checked,
41
+ }
42
+ }));
43
+
44
+ const onChange = (item: any) => {
45
+ const newLang = languages.filter((lang: any) => lang.lang !== item.lang)
46
+ setLanguages([...newLang, item].sort((a, b) => {
47
+ return a.value.localeCompare(b.value)
48
+ }))
49
+ }
50
+
51
+ const apply = () => {
52
+ const selectedLanguages = languages.filter((item: any) => item.checked).map((item: any) => item.value).join(',')
53
+ setContentLanguage(selectedLanguages)
54
+ }
55
+
56
+ return (
57
+ <Dialog>
58
+ <DialogTrigger asChild>
59
+ {trigger}
60
+ </DialogTrigger>
61
+ <DialogContent>
62
+ <DialogHeader>
63
+ <DialogTitle>{t("filters")}</DialogTitle>
64
+ </DialogHeader>
65
+ <div className="grid grid-cols-2 items-center py-4">
66
+ <Label className="text-right">
67
+ {t("languages")}:
68
+ </Label>
69
+ <div className="flex items-center">
70
+ {languages?.map((item: any, index: any) => {
71
+ return (
72
+ <div key={index} className="mr-4">
73
+ <Checkbox
74
+ id={`available-languages${item.lang}`}
75
+ className="mr-2"
76
+ {...({ checked: item.checked })}
77
+ onCheckedChange={(checked: boolean) => onChange({
78
+ ...item,
79
+ checked: checked,
80
+ })}
81
+ />
82
+ <label
83
+ htmlFor={`available-languages${item.lang}`}
84
+ className="text-sm font-medium "
85
+ >
86
+ {item.lang.toUpperCase()}
87
+ </label>
88
+ </div>
89
+ )
90
+ })}
91
+ </div>
92
+
93
+ </div>
94
+ <DialogFooter>
95
+ <DialogClose asChild>
96
+ <Button onClick={apply}>{t("applyFilters")}</Button>
97
+ </DialogClose>
98
+ </DialogFooter>
99
+ </DialogContent>
100
+ </Dialog>
101
+ )
102
+ }
package/src/empty.tsx CHANGED
@@ -1,12 +1,15 @@
1
- import { FC } from "react";
1
+ import React, { FC } from "react";
2
2
  import { Alert, AlertDescription, AlertTitle } from "@c-rex/ui/alert";
3
+ import { useTranslations } from "next-intl";
3
4
 
4
5
  export const Empty: FC = () => {
6
+ const t = useTranslations("results")
7
+
5
8
  return (
6
9
  <Alert className="my-2">
7
- <AlertTitle>No results</AlertTitle>
10
+ <AlertTitle>{t("noResultsTitle")}</AlertTitle>
8
11
  <AlertDescription>
9
- No data available. Please try adjusting your search or filter criteria.
12
+ {t("noResultsDescription")}
10
13
  </AlertDescription>
11
14
  </Alert>
12
15
  );
@@ -0,0 +1,35 @@
1
+ 'use client'
2
+
3
+ import React, { FC, startTransition } from "react";
4
+ import { LanguageAndCountries } from "@c-rex/interfaces";
5
+ import { SharedLanguageSwitch } from "./shared";
6
+ import { setCookie } from "@c-rex/utils/next-cookies";
7
+ import { CONTENT_LANG_KEY, DEFAULT_UI_LANG } from "@c-rex/constants";
8
+ import { useQueryState } from "nuqs"
9
+
10
+ interface ContentLanguageSwitchProps {
11
+ availableLanguagesAndCountries: LanguageAndCountries[];
12
+ }
13
+ export const ContentLanguageSwitch: FC<ContentLanguageSwitchProps> = ({ availableLanguagesAndCountries }) => {
14
+
15
+ const [contentLanguage, setContentLanguage] = useQueryState('language', {
16
+ history: 'push',
17
+ shallow: false,
18
+ defaultValue: DEFAULT_UI_LANG
19
+ })
20
+
21
+ const changeContentLanguage = (locale: string) => {
22
+ startTransition(() => {
23
+ setCookie(CONTENT_LANG_KEY, locale)
24
+ setContentLanguage(locale)
25
+ });
26
+ };
27
+
28
+ return (
29
+ <SharedLanguageSwitch
30
+ availableLanguagesAndCountries={availableLanguagesAndCountries}
31
+ changeLanguage={changeContentLanguage}
32
+ selected={contentLanguage}
33
+ />
34
+ );
35
+ };
@@ -0,0 +1,33 @@
1
+ import React, { FC, JSX } from "react";
2
+ import * as Flags from 'country-flag-icons/react/3x2';
3
+ import { LanguageAndCountries } from "@c-rex/interfaces";
4
+ import { DropdownMenuRadioGroup, DropdownMenuRadioItem } from "@c-rex/ui/dropdown-menu";
5
+
6
+ interface SharedLanguageSwitchProps {
7
+ availableLanguagesAndCountries: LanguageAndCountries[];
8
+ selected: string;
9
+ changeLanguage: (locale: string) => void;
10
+ }
11
+ export const SharedLanguageSwitch: FC<SharedLanguageSwitchProps> = ({ availableLanguagesAndCountries, changeLanguage, selected }) => {
12
+
13
+ const getFlagIcon = (countryCode: string): JSX.Element | null => {
14
+ type CountryCode = keyof typeof Flags;
15
+ const FlagComponent = Flags[countryCode as CountryCode];
16
+ if (!FlagComponent) return null;
17
+
18
+ return <FlagComponent />;
19
+ };
20
+
21
+ return (
22
+ <DropdownMenuRadioGroup value={selected} onValueChange={changeLanguage}>
23
+ {availableLanguagesAndCountries.map(item => {
24
+ return (
25
+ <DropdownMenuRadioItem key={item.value} value={item.value}>
26
+ <span>{item.lang.toUpperCase()}</span>
27
+ {getFlagIcon(item.country)}
28
+ </DropdownMenuRadioItem>
29
+ )
30
+ })}
31
+ </DropdownMenuRadioGroup>
32
+ );
33
+ };
@@ -0,0 +1,38 @@
1
+ "use client"
2
+
3
+ import React, { FC, startTransition, useEffect, useState } from "react";
4
+ import { LanguageAndCountries } from "@c-rex/interfaces";
5
+ import { SharedLanguageSwitch } from "./shared";
6
+ import { setCookie } from "@c-rex/utils/next-cookies";
7
+ import { DEFAULT_UI_LANG, UI_LANG_KEY } from "@c-rex/constants";
8
+
9
+ interface UILanguageSwitchProps {
10
+ availableLanguagesAndCountries: LanguageAndCountries[];
11
+ }
12
+ export const UILanguageSwitch: FC<UILanguageSwitchProps> = ({ availableLanguagesAndCountries }) => {
13
+ const [selected, setSelected] = useState(DEFAULT_UI_LANG);
14
+
15
+ useEffect(() => {
16
+ const allCookies = document.cookie
17
+ const uiLang = allCookies
18
+ .split('; ')
19
+ .find(row => row.startsWith(`${UI_LANG_KEY}=`))
20
+ ?.split('=')[1]
21
+ setSelected(uiLang as string)
22
+ }, [])
23
+
24
+
25
+ const setUILanguage = (locale: string) => {
26
+ startTransition(() => {
27
+ setCookie(UI_LANG_KEY, locale)
28
+ });
29
+ }
30
+
31
+ return (
32
+ <SharedLanguageSwitch
33
+ availableLanguagesAndCountries={availableLanguagesAndCountries}
34
+ changeLanguage={setUILanguage}
35
+ selected={selected}
36
+ />
37
+ );
38
+ };
@@ -1,12 +1,28 @@
1
1
  import React, { FC } from "react";
2
2
  import Link from "next/link";
3
3
  import Image from "next/image";
4
- import { SingOut, SingInBtn } from "./sing-in-out-btns";
4
+ import { SignOut, SignInBtn } from "./sign-in-out-btns";
5
5
  import { getServerSession } from "next-auth";
6
- import { getFromMemory } from "@c-rex/utils";
7
- import { SDK_CONFIG_KEY } from "@c-rex/constants";
6
+ import { getCookie } from '@c-rex/utils/next-cookies';
8
7
  import { ConfigInterface } from "@c-rex/interfaces";
9
-
8
+ import {
9
+ DropdownMenu,
10
+ DropdownMenuContent,
11
+ DropdownMenuLabel,
12
+ DropdownMenuPortal,
13
+ DropdownMenuSeparator,
14
+ DropdownMenuSub,
15
+ DropdownMenuSubContent,
16
+ DropdownMenuSubTrigger,
17
+ DropdownMenuTrigger,
18
+ } from "@c-rex/ui/dropdown-menu"
19
+ import { SDK_CONFIG_KEY, UI_LANG_OPTIONS } from "@c-rex/constants";
20
+ import { LanguageService } from "@c-rex/services";
21
+ import { Settings } from "lucide-react";
22
+ import { ContentLanguageSwitch } from "./language-switcher/content-language-switch";
23
+ import { getTranslations } from "next-intl/server";
24
+ import { getCountryCodeByLang } from "@c-rex/utils";
25
+ import { UILanguageSwitch } from "./language-switcher/ui-language-switch";
10
26
 
11
27
  interface NavBarProps {
12
28
  scroll?: boolean;
@@ -14,8 +30,23 @@ interface NavBarProps {
14
30
  }
15
31
 
16
32
  export const NavBar: FC<NavBarProps> = async () => {
33
+ const t = await getTranslations();
17
34
  const session = await getServerSession()
18
- const configs: ConfigInterface = await getFromMemory(SDK_CONFIG_KEY)
35
+
36
+ const jsonConfigs = await getCookie(SDK_CONFIG_KEY);
37
+ if (!jsonConfigs) {
38
+ return null;
39
+ }
40
+
41
+ const configs: ConfigInterface = JSON.parse(jsonConfigs);
42
+ const service = new LanguageService(configs.languageSwitcher.endpoint);
43
+ const contentLanguages = await service.getLanguagesAndCountries();
44
+
45
+ const UILanguages = UI_LANG_OPTIONS.map((lang) => ({
46
+ value: lang,
47
+ lang: lang,
48
+ country: getCountryCodeByLang(lang)
49
+ }));
19
50
 
20
51
  return (
21
52
  <header className="sticky top-0 z-40 flex w-full bg-background/60 backdrop-blur-xl transition-all bg-transparent border-b justify-center py-4">
@@ -29,46 +60,64 @@ export const NavBar: FC<NavBarProps> = async () => {
29
60
  height={50}
30
61
  />
31
62
  </Link>
63
+ {configs.projectName}
64
+ </div>
32
65
 
33
- <nav className="hidden gap-6 md:flex">
34
- {/*
35
- TODO: add map to load links
36
- TODO: add function to validate active item
37
- */}
38
- <Link
39
- href={"/blog"}
40
- prefetch={true}
41
- className={
42
- "flex items-center text-lg font-medium transition-colors hover:text-foreground/80 sm:text-sm"
43
- }
44
- >
45
- Blog
46
- </Link>
66
+ <div className="flex items-center space-x-3">
67
+ {configs.OIDC.user.enabled && (
68
+ <>
69
+ {session ? (
70
+ <>
71
+ <span>{t("user.welcome", { userName: session.user?.name as string })}</span>
72
+ <SignOut />
73
+ </>
74
+ ) : (
75
+ <SignInBtn />
76
+ )}
77
+ </>
78
+ )}
47
79
 
48
- <Link
49
- href={"#"}
50
- prefetch={true}
51
- className={
52
- "flex items-center text-lg font-medium transition-colors hover:text-foreground/80 sm:text-sm"
53
- }
54
- >
55
- Documentation
56
- </Link>
57
- </nav>
58
- </div>
80
+ {configs.languageSwitcher.enabled && (
81
+ <DropdownMenu>
82
+ <DropdownMenuTrigger>
83
+ <Settings />
84
+ </DropdownMenuTrigger>
85
+ <DropdownMenuContent>
86
+ <DropdownMenuLabel>{t("accountSettings.accountSettings")}</DropdownMenuLabel>
87
+ <DropdownMenuSeparator />
59
88
 
60
- {configs.OIDC.user.enabled && (
61
- <div className="flex items-center space-x-3">
62
- {session ? (
63
- <>
64
- <span>Welcome, {session.user?.name}</span>
65
- <SingOut />
66
- </>
67
- ) : (
68
- <SingInBtn />
69
- )}
70
- </div>
71
- )}
89
+ <DropdownMenuSub>
90
+ <DropdownMenuSubTrigger>
91
+ <span>{t("accountSettings.contentLanguage")}</span>
92
+ </DropdownMenuSubTrigger>
93
+
94
+ <DropdownMenuPortal>
95
+ <DropdownMenuSubContent>
96
+ <ContentLanguageSwitch
97
+ availableLanguagesAndCountries={contentLanguages}
98
+ />
99
+ </DropdownMenuSubContent>
100
+ </DropdownMenuPortal>
101
+ </DropdownMenuSub>
102
+
103
+
104
+ <DropdownMenuSub>
105
+ <DropdownMenuSubTrigger>
106
+ <span>{t("accountSettings.uiLanguage")}</span>
107
+ </DropdownMenuSubTrigger>
108
+
109
+ <DropdownMenuPortal>
110
+ <DropdownMenuSubContent>
111
+ <UILanguageSwitch
112
+ availableLanguagesAndCountries={UILanguages}
113
+ />
114
+ </DropdownMenuSubContent>
115
+ </DropdownMenuPortal>
116
+ </DropdownMenuSub>
117
+ </DropdownMenuContent>
118
+ </DropdownMenu>
119
+ )}
120
+ </div>
72
121
  </div>
73
122
  </header>
74
123
  );
@@ -0,0 +1,36 @@
1
+ "use client"
2
+
3
+ import React from "react";
4
+ import { signOut, signIn } from "next-auth/react";
5
+ import { Button } from "@c-rex/ui/button";
6
+ import { useTranslations } from "next-intl";
7
+
8
+ export const SignInBtn = () => {
9
+ const t = useTranslations("user")
10
+ return (
11
+ <Button
12
+ className="gap-2 px-5 md:flex"
13
+ variant="default"
14
+ size="sm"
15
+ rounded="full"
16
+ onClick={() => signIn("crex", { callbackUrl: "/" })}
17
+ >
18
+ <span>{t("signIn")}</span>
19
+ </Button>
20
+ );
21
+ }
22
+
23
+ export const SignOut = () => {
24
+ const t = useTranslations("user")
25
+ return (
26
+ <Button
27
+ className="gap-2 px-5 md:flex"
28
+ variant="default"
29
+ size="sm"
30
+ rounded="full"
31
+ onClick={() => signOut()}
32
+ >
33
+ <span>{t("signOut")}</span>
34
+ </Button>
35
+ );
36
+ }
@@ -1,16 +1,22 @@
1
- import { FC } from "react";
2
- import { informationUnitsItems } from "@c-rex/interfaces";
1
+ import React, { FC } from "react";
2
+ import { ConfigInterface, informationUnitsItems } from "@c-rex/interfaces";
3
3
  import { Empty } from "./empty";
4
- //import { CUSTOMER_CONFIG } from '@/config/customerConfig';
5
- //import { RESULT_VIEW_OPTIONS } from '@/constants/components';
6
4
  import BlogView from './result-view/blog';
7
-
8
- const ViewComponent = BlogView;
5
+ import TableView from './result-view/table';
9
6
 
10
7
  interface ResultListProps {
11
8
  items: informationUnitsItems[];
9
+ configs: ConfigInterface
12
10
  }
13
11
 
14
- export const ResultList: FC<ResultListProps> = ({ items }) => {
15
- return <>{items.length == 0 ? <Empty /> : <ViewComponent items={items} />}</>;
12
+ export const ResultList: FC<ResultListProps> = ({ items, configs }) => {
13
+ const ViewComponent = configs.resultViewStyle == "table" ? TableView : BlogView;
14
+
15
+ return (
16
+ <>
17
+ {
18
+ items.length == 0 ? <Empty /> : <ViewComponent items={items} />
19
+ }
20
+ </>
21
+ );
16
22
  };
@@ -1,5 +1,4 @@
1
- import { FC } from "react";
2
-
1
+ import React, { FC } from "react";
3
2
  import { BlogCard } from "../blog-card";
4
3
  import { informationUnitsItems, Labels } from "@c-rex/interfaces";
5
4
 
@@ -9,6 +8,9 @@ interface BlogViewProps {
9
8
 
10
9
  const BlogView: FC<BlogViewProps> = ({ items }) => {
11
10
  const getTitle = (labels: Labels[]): string => {
11
+ if (labels === undefined) {
12
+ return "";
13
+ }
12
14
  return labels.map((item) => item.value).join();
13
15
  };
14
16
 
@@ -1,5 +1,4 @@
1
- import { FC, ReactNode } from "react";
2
-
1
+ import React, { FC, ReactNode } from "react";
3
2
  import {
4
3
  Table,
5
4
  TableBody,
@@ -8,36 +7,21 @@ import {
8
7
  TableRow,
9
8
  } from "@c-rex/ui/table";
10
9
  import { informationUnitsItems, Labels } from "@c-rex/interfaces";
11
- //import { getFlagIcon } from '@c-rex/utils/index';
10
+ import Link from "next/link";
11
+ import { useTranslations } from "next-intl";
12
12
 
13
13
  interface TableViewProps {
14
14
  items: informationUnitsItems[];
15
15
  }
16
16
 
17
17
  const TableView: FC<TableViewProps> = ({ items }) => {
18
+ const t = useTranslations("results")
19
+
18
20
  const getTitle = (labels: Labels[]): string => {
19
21
  return labels.map((item) => item.value).join();
20
22
  };
21
- const getIcons = (languages: string[]): ReactNode[] => {
22
- return languages.map((lang, index) => {
23
- const aux = lang.split("-")[1];
24
-
25
- /*
26
- const FlagIcon = getFlagIcon(aux);
27
-
28
- return FlagIcon && (
29
- <div key={index} style={{ width: 36 }} className="border me-3">
30
- <FlagIcon />
31
- </div>
32
- )
33
- */
34
-
35
- return (
36
- <div key={index} style={{ width: 36 }} className="border me-3">
37
- {aux}
38
- </div>
39
- );
40
- });
23
+ const getIcons = (languages: string[]): string => {
24
+ return languages.map((lang) => lang.split("-")[1]).join(",");
41
25
  };
42
26
 
43
27
  return (
@@ -45,14 +29,20 @@ const TableView: FC<TableViewProps> = ({ items }) => {
45
29
  <Table>
46
30
  <TableHeader>
47
31
  <TableRow>
48
- <TableCell>Title</TableCell>
49
- <TableCell>Country</TableCell>
32
+ <TableCell>{t("title")}</TableCell>
33
+ <TableCell>{t("language")}</TableCell>
50
34
  </TableRow>
51
35
  </TableHeader>
52
36
  <TableBody>
53
37
  {items.map((item: informationUnitsItems, index: number) => (
54
38
  <TableRow key={index}>
55
- <TableCell>{getTitle(item.labels)}</TableCell>
39
+ <Link
40
+ key={index}
41
+ href={`info/${item.shortId}`}
42
+ target="_blank"
43
+ >
44
+ <TableCell>{getTitle(item.labels)}</TableCell>
45
+ </Link>
56
46
  <TableCell>{getIcons(item.languages)}</TableCell>
57
47
  </TableRow>
58
48
  ))}
package/src/sidebar.tsx CHANGED
@@ -1,10 +1,11 @@
1
1
  "use client";
2
2
 
3
- import { ComponentProps } from "react";
3
+ import React, { ComponentProps, JSX } from "react";
4
4
  import {
5
5
  Sidebar,
6
6
  SidebarContent,
7
7
  SidebarGroup,
8
+ SidebarGroupLabel,
8
9
  SidebarMenu,
9
10
  SidebarMenuButton,
10
11
  SidebarMenuItem,
@@ -15,18 +16,32 @@ import {
15
16
  } from "@c-rex/ui/sidebar";
16
17
  import { Skeleton } from "@c-rex/ui/skeleton";
17
18
  import { TreeOfContent } from "@c-rex/interfaces";
19
+ import * as Flags from 'country-flag-icons/react/3x2';
20
+ import { useTranslations } from "next-intl";
18
21
 
19
22
  interface SidebarProps extends ComponentProps<typeof Sidebar> {
20
23
  data: TreeOfContent[];
21
24
  loading?: boolean;
25
+ availableVersions: any
22
26
  }
23
27
 
24
- export function AppSidebar({ data, loading, ...props }: SidebarProps) {
28
+ export function AppSidebar({ data, availableVersions, loading, ...props }: SidebarProps) {
29
+ const t = useTranslations();
30
+
31
+ const getFlagIcon = (countryCode: string): JSX.Element | null => {
32
+ type CountryCode = keyof typeof Flags;
33
+ const FlagComponent = Flags[countryCode as CountryCode];
34
+ if (!FlagComponent) return null;
35
+
36
+ return <FlagComponent />;
37
+ };
38
+
25
39
  return (
26
- <Sidebar collapsible="icon" {...props} className="top-20">
40
+ <Sidebar collapsible="icon" {...props}>
27
41
  <SidebarContent>
28
- <SidebarGroup>
29
- <SidebarMenu className="pt-4">
42
+ <SidebarGroup className="my-4">
43
+ <SidebarGroupLabel>{t("tableOfContent")}:</SidebarGroupLabel>
44
+ <SidebarMenu>
30
45
  {loading ? (
31
46
  <>
32
47
  <Skeleton className="w-auto h-10 mb-2" />
@@ -69,6 +84,25 @@ export function AppSidebar({ data, loading, ...props }: SidebarProps) {
69
84
  )}
70
85
  </SidebarMenu>
71
86
  </SidebarGroup>
87
+
88
+ <SidebarGroup>
89
+ <SidebarGroupLabel>{t("availableIn")}:</SidebarGroupLabel>
90
+ <SidebarMenu>
91
+
92
+ {availableVersions.map((item: any) => {
93
+ return (
94
+
95
+ <SidebarMenuItem key={item.shortId}>
96
+ <SidebarMenuButton asChild isActive={item.active}>
97
+ <a href={`../info/${item.shortId}`} title={item.lang}>
98
+ {getFlagIcon(item.country)} {item.lang}
99
+ </a>
100
+ </SidebarMenuButton>
101
+ </SidebarMenuItem>
102
+ )
103
+ })}
104
+ </SidebarMenu>
105
+ </SidebarGroup>
72
106
  </SidebarContent>
73
107
  <SidebarRail />
74
108
  </Sidebar>
@@ -1,29 +0,0 @@
1
- "use client"
2
-
3
- import React from "react";
4
- import { signOut, signIn } from "next-auth/react";
5
- import { Button } from "@c-rex/ui/button";
6
-
7
- export const SingInBtn = () => (
8
- <Button
9
- className="hidden gap-2 px-5 md:flex"
10
- variant="default"
11
- size="sm"
12
- rounded="full"
13
- onClick={() => signIn("crex", { callbackUrl: "/" })}
14
- >
15
- <span>Sign In</span>
16
- </Button>
17
- );
18
-
19
- export const SingOut = () => (
20
- <Button
21
- className="hidden gap-2 px-5 md:flex"
22
- variant="default"
23
- size="sm"
24
- rounded="full"
25
- onClick={() => signOut()}
26
- >
27
- <span>Sign out</span>
28
- </Button>
29
- );
@@ -1,21 +0,0 @@
1
- "use client";
2
-
3
- import { SearchProvider } from "@c-rex/contexts";
4
- import { FC, ReactNode } from "react";
5
-
6
- interface SearchStateWrapperProps {
7
- children: ReactNode;
8
- filters: {
9
- searchValue: string;
10
- page: number;
11
- selectedLanguage: string[];
12
- availableLanguages: string[];
13
- };
14
- }
15
-
16
- export const SearchStateWrapper: FC<SearchStateWrapperProps> = ({
17
- children,
18
- filters,
19
- }) => {
20
- return <SearchProvider value={{ ...filters }}>{children}</SearchProvider>;
21
- };