Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

page.tsx 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. 'use client';
  2. import React, { useEffect, useState } from 'react';
  3. import PageTitle from '@/components/ui/PageTitle';
  4. import {
  5. EyeOutlined,
  6. EditOutlined,
  7. SortAscendingOutlined,
  8. PlusCircleFilled
  9. } from '@ant-design/icons';
  10. import type { Persona } from '@/types/persona';
  11. import { getPersona } from '@/app/api/user/personaService';
  12. import { useQuery } from '@tanstack/react-query';
  13. import PrimaryButton from '@/components/ui/PrimaryButton';
  14. import { Flex, Row, Col, Tag, Button, Table, Layout, Image, Typography } from 'antd';
  15. import type { ColumnsType } from 'antd/es/table';
  16. import { useRouter } from 'next/navigation';
  17. const {Text, Title} = Typography;
  18. const columns: ColumnsType<Persona> = [
  19. {
  20. title: (
  21. <Text className="flex items-center gap-1">
  22. Name <SortAscendingOutlined className="text-xs text-gray-400" />
  23. </Text>
  24. ),
  25. dataIndex: 'name',
  26. key: 'name',
  27. },
  28. {
  29. title: (
  30. <Text className="flex items-center gap-1">
  31. Role <SortAscendingOutlined className="text-xs text-gray-400" />
  32. </Text>
  33. ),
  34. dataIndex: 'role',
  35. key: 'role',
  36. },
  37. {
  38. title: (
  39. <Text className="flex items-center gap-1">
  40. Status <SortAscendingOutlined className="text-xs text-gray-400" />
  41. </Text>
  42. ),
  43. dataIndex: 'active',
  44. key: 'status',
  45. align: 'center' as const,
  46. render: (active: boolean) => (
  47. <Tag color={active ? 'green' : 'orange'} className="!rounded-full">
  48. {active ? 'Active' : 'Inactive'}
  49. </Tag>
  50. ),
  51. },
  52. {
  53. title: 'Action',
  54. key: 'action',
  55. align: 'center' as const,
  56. render: (_: any, record: Persona) => (
  57. <Flex justify="center">
  58. <Button type="text" icon={<EditOutlined />} />
  59. <Button type="text" icon={<EyeOutlined />} />
  60. </Flex>
  61. ),
  62. },
  63. ];
  64. const PersonaPage: React.FC = () => {
  65. const { data: personas, error, isLoading } = useQuery<Persona[]>({
  66. queryKey: ["getPersona"],
  67. queryFn: () => getPersona()
  68. })
  69. if (isLoading) {
  70. return <p>Loading...</p>
  71. }
  72. if (!personas) {
  73. return <p></p>
  74. }
  75. return (
  76. <Flex vertical className="!bg-white !h-full">
  77. <PageTitle>PERSONA</PageTitle>
  78. {(personas.length > 0) ? <PersonaList personaData={personas} /> : <PersonaIntro />}
  79. </Flex>
  80. );
  81. };
  82. const PersonaIntro: React.FC = () => {
  83. const router = useRouter();
  84. return (
  85. <Flex vertical flex={1} justify="center" align="center">
  86. <Row justify="center" style={{ width: '100%', padding: '0 24px' }}>
  87. <Col xs={24} sm={20} md={16} lg={12} xl={8}>
  88. <Flex
  89. vertical
  90. align="center"
  91. className="!text-center"
  92. style={{
  93. border: '2px solid #06b6d4', // cyan-500
  94. borderRadius: '12px',
  95. padding: '40px 24px',
  96. boxShadow: '0 10px 100px 30px rgba(59, 130, 246, 0.3)',
  97. background: 'white',
  98. }}
  99. >
  100. <Title level={5} style={{ marginBottom: 8, color: '#1f2937' }}>NO PERSONA CREATED YET</Title>
  101. <Text type="secondary" style={{ marginBottom: 24 }}>
  102. Get started by creating your first AI Persona
  103. </Text>
  104. <Image
  105. src="/Ruccan_Logo2.png"
  106. alt="Ruccan Logo"
  107. width={150}
  108. preview={false}
  109. style={{ marginBottom: 24 }}
  110. />
  111. <PrimaryButton onClick={() => router.push('/user/persona/create')}>
  112. CREATE YOUR FIRST PERSONA
  113. </PrimaryButton>
  114. </Flex>
  115. </Col>
  116. </Row>
  117. </Flex>
  118. )
  119. }
  120. interface PersonaListProps {
  121. personaData: Persona[] | undefined;
  122. }
  123. const PersonaList: React.FC<PersonaListProps> = ({ personaData }) => {
  124. const router = useRouter();
  125. return (
  126. <Layout className="!overflow-x-auto">
  127. <Flex className='!px-2 !py-4 !justify-end'>
  128. <PrimaryButton onClick={() => { router.push('persona/create') }}>
  129. <PlusCircleFilled /> Create New Persona
  130. </PrimaryButton>
  131. </Flex>
  132. <Table
  133. className="[&_.ant-table-cell]:!p-2"
  134. rowKey="id"
  135. columns={columns}
  136. dataSource={personaData}
  137. pagination={false}
  138. bordered
  139. />
  140. </Layout>
  141. );
  142. };
  143. export default PersonaPage;