@geenius/feedback 0.1.0 → 0.3.0
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 +16 -3
- package/packages/convex/dist/index.d.ts +192 -0
- package/packages/convex/dist/index.js +239 -0
- package/packages/convex/dist/index.js.map +1 -0
- package/packages/react/README.md +1 -1
- package/packages/react/dist/index.d.ts +146 -0
- package/packages/react/dist/index.js +545 -0
- package/packages/react/dist/index.js.map +1 -0
- package/packages/react-css/README.md +1 -1
- package/packages/react-css/dist/index.css +965 -0
- package/packages/react-css/dist/index.css.map +1 -0
- package/packages/react-css/dist/index.d.ts +49 -0
- package/packages/react-css/dist/index.js +228 -0
- package/packages/react-css/dist/index.js.map +1 -0
- package/packages/shared/README.md +1 -1
- package/packages/shared/dist/index.d.ts +115 -0
- package/packages/shared/dist/index.js +112 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/packages/solidjs/README.md +1 -1
- package/packages/solidjs/dist/index.d.ts +128 -0
- package/packages/solidjs/dist/index.js +289 -0
- package/packages/solidjs/dist/index.js.map +1 -0
- package/packages/solidjs-css/README.md +1 -1
- package/packages/solidjs-css/dist/index.css +965 -0
- package/packages/solidjs-css/dist/index.css.map +1 -0
- package/packages/solidjs-css/dist/index.d.ts +2 -0
- package/packages/solidjs-css/dist/index.js +29 -0
- package/packages/solidjs-css/dist/index.js.map +1 -0
- package/.changeset/config.json +0 -11
- package/.github/CODEOWNERS +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -23
- package/.github/workflows/release.yml +0 -29
- package/.nvmrc +0 -1
- package/.project/ACCOUNT.yaml +0 -4
- package/.project/IDEAS.yaml +0 -7
- package/.project/PROJECT.yaml +0 -11
- package/.project/ROADMAP.yaml +0 -15
- package/CODE_OF_CONDUCT.md +0 -16
- package/CONTRIBUTING.md +0 -26
- package/SECURITY.md +0 -15
- package/SUPPORT.md +0 -8
- package/packages/convex/package.json +0 -42
- package/packages/convex/src/index.ts +0 -3
- package/packages/convex/src/mutations.ts +0 -88
- package/packages/convex/src/queries.ts +0 -78
- package/packages/convex/src/schema.ts +0 -47
- package/packages/convex/tsconfig.json +0 -18
- package/packages/convex/tsup.config.ts +0 -17
- package/packages/react/package.json +0 -49
- package/packages/react/src/components/FeedbackCard.tsx +0 -51
- package/packages/react/src/components/FeedbackForm.tsx +0 -43
- package/packages/react/src/components/FeedbackWidget.tsx +0 -32
- package/packages/react/src/components/NPSSurvey.tsx +0 -62
- package/packages/react/src/components/index.ts +0 -4
- package/packages/react/src/hooks/index.ts +0 -5
- package/packages/react/src/hooks/useFeedback.ts +0 -23
- package/packages/react/src/hooks/useFeedbackAdmin.ts +0 -24
- package/packages/react/src/hooks/useFeedbackForm.ts +0 -35
- package/packages/react/src/hooks/useNPS.ts +0 -26
- package/packages/react/src/index.tsx +0 -13
- package/packages/react/src/pages/FeedbackAdminPage.tsx +0 -71
- package/packages/react/src/pages/FeedbackPublicPage.tsx +0 -42
- package/packages/react/src/pages/FeedbackWidgetPage.tsx +0 -25
- package/packages/react/src/pages/index.ts +0 -3
- package/packages/react/tsconfig.json +0 -19
- package/packages/react/tsup.config.ts +0 -12
- package/packages/react-css/package.json +0 -36
- package/packages/react-css/src/components/index.ts +0 -5
- package/packages/react-css/src/components/index.tsx +0 -107
- package/packages/react-css/src/hooks/index.ts +0 -2
- package/packages/react-css/src/index.tsx +0 -5
- package/packages/react-css/src/pages/FeedbackAdminPage.tsx +0 -112
- package/packages/react-css/src/pages/FeedbackPage.tsx +0 -76
- package/packages/react-css/src/styles.css +0 -281
- package/packages/react-css/tsconfig.json +0 -19
- package/packages/react-css/tsup.config.ts +0 -10
- package/packages/shared/package.json +0 -44
- package/packages/shared/src/__tests__/feedback.test.ts +0 -72
- package/packages/shared/src/config.ts +0 -49
- package/packages/shared/src/index.ts +0 -111
- package/packages/shared/src/types.ts +0 -59
- package/packages/shared/tsconfig.json +0 -18
- package/packages/shared/tsup.config.ts +0 -11
- package/packages/shared/vitest.config.ts +0 -4
- package/packages/solidjs/package.json +0 -45
- package/packages/solidjs/src/components.tsx +0 -72
- package/packages/solidjs/src/index.tsx +0 -3
- package/packages/solidjs/src/primitives.ts +0 -49
- package/packages/solidjs/tsconfig.json +0 -20
- package/packages/solidjs/tsup.config.ts +0 -12
- package/packages/solidjs-css/package.json +0 -32
- package/packages/solidjs-css/src/index.tsx +0 -4
- package/packages/solidjs-css/src/pages/FeedbackAdminPage.tsx +0 -78
- package/packages/solidjs-css/src/pages/FeedbackPage.tsx +0 -65
- package/packages/solidjs-css/src/primitives/index.ts +0 -1
- package/packages/solidjs-css/src/styles.css +0 -281
- package/packages/solidjs-css/tsconfig.json +0 -20
- package/packages/solidjs-css/tsup.config.ts +0 -10
- package/pnpm-workspace.yaml +0 -2
- package/tsconfig.json +0 -23
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@geenius-feedback/react-css",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "Geenius Feedback — React components & hooks (vanilla CSS variant)",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"publishConfig": {
|
|
8
|
-
"access": "restricted"
|
|
9
|
-
},
|
|
10
|
-
"main": "./src/index.tsx",
|
|
11
|
-
"types": "./src/index.tsx",
|
|
12
|
-
"exports": {
|
|
13
|
-
".": "./src/index.tsx"
|
|
14
|
-
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"type-check": "tsc --noEmit"
|
|
17
|
-
},
|
|
18
|
-
"peerDependencies": {
|
|
19
|
-
"react": ">=18.0.0",
|
|
20
|
-
"react-dom": ">=18.0.0"
|
|
21
|
-
},
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"@geenius-feedback/shared": "workspace:*"
|
|
24
|
-
},
|
|
25
|
-
"devDependencies": {
|
|
26
|
-
"@types/react": "^19.0.7",
|
|
27
|
-
"@types/react-dom": "^19.0.3",
|
|
28
|
-
"react": "^19.0.0",
|
|
29
|
-
"react-dom": "^19.0.0",
|
|
30
|
-
"typescript": "~6.0.2"
|
|
31
|
-
},
|
|
32
|
-
"author": "Antigravity HQ",
|
|
33
|
-
"engines": {
|
|
34
|
-
"node": ">=20.0.0"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @geenius-feedback/react — src/components/index.ts
|
|
2
|
-
|
|
3
|
-
export { FeedbackForm, type FeedbackFormProps } from './FeedbackForm'
|
|
4
|
-
export { FeedbackWidget, type FeedbackWidgetProps } from './FeedbackWidget'
|
|
5
|
-
export { FeedbackButton, type FeedbackButtonProps } from './FeedbackButton'
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
2
|
-
import type { FeedbackItem, FeedbackType, FeedbackStatus, FeedbackPriority, NPSResponse } from '@geenius-feedback/shared'
|
|
3
|
-
import { STATUS_CONFIG, PRIORITY_CONFIG, TYPE_CONFIG, FEEDBACK_TYPES, formatRelativeTime, calcNPSStats, getNPSCategory } from '@geenius-feedback/shared'
|
|
4
|
-
import type { RuleOperator } from '@geenius-feedback/shared'
|
|
5
|
-
|
|
6
|
-
export function StatusBadge({ status }: { status: FeedbackStatus }) {
|
|
7
|
-
return <span className={`feedback__status-badge feedback__status-badge--${status}`}>{STATUS_CONFIG[status].emoji} {STATUS_CONFIG[status].label}</span>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function PriorityBadge({ priority }: { priority: FeedbackPriority }) {
|
|
11
|
-
return <span className={`feedback__priority-badge feedback__priority-badge--${priority}`}>{PRIORITY_CONFIG[priority].label}</span>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function TypeBadge({ type }: { type: FeedbackType }) {
|
|
15
|
-
return <span className={`feedback__type-badge feedback__type-badge--${type}`}>{TYPE_CONFIG[type].icon} {TYPE_CONFIG[type].label}</span>
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function FeedbackCard({ item, onVote, hasVoted, onClick }: { item: FeedbackItem; onVote?: (id: string) => void; hasVoted?: boolean; onClick?: (id: string) => void }) {
|
|
19
|
-
return (
|
|
20
|
-
<div className={`feedback__card feedback__card--${item.type}`} onClick={() => onClick?.(item.id)}>
|
|
21
|
-
{onVote && (
|
|
22
|
-
<button type="button" className={`feedback__vote-btn ${hasVoted ? 'feedback__vote-btn--active' : 'feedback__vote-btn--inactive'}`} onClick={e => { e.stopPropagation(); onVote(item.id) }}>
|
|
23
|
-
<span className="feedback__vote-btn-arrow">{hasVoted ? '▲' : '△'}</span>
|
|
24
|
-
<span>{item.votes}</span>
|
|
25
|
-
</button>
|
|
26
|
-
)}
|
|
27
|
-
<div className="feedback__card-info">
|
|
28
|
-
<div className="feedback__card-badges"><TypeBadge type={item.type} /><StatusBadge status={item.status} /><PriorityBadge priority={item.priority} /></div>
|
|
29
|
-
<div className="feedback__card-title">{item.title}</div>
|
|
30
|
-
<div className="feedback__card-desc">{item.description}</div>
|
|
31
|
-
<div className="feedback__card-meta">{item.userName && <span>{item.userName}</span>}<span>{formatRelativeTime(item.createdAt)}</span>{item.tags.map(t => <span key={t} className="feedback__tag">{t}</span>)}</div>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function FeedbackTypeSelector({ value, onChange }: { value: FeedbackType; onChange: (t: FeedbackType) => void }) {
|
|
38
|
-
return (
|
|
39
|
-
<div className="feedback__type-selector">
|
|
40
|
-
{FEEDBACK_TYPES.map(t => <button key={t} type="button" onClick={() => onChange(t)}
|
|
41
|
-
className={`feedback__type-tab ${value === t ? '' : 'feedback__type-tab--inactive'}`}
|
|
42
|
-
style={value === t ? { background: TYPE_CONFIG[t].color, color: 'white' } : undefined}>{TYPE_CONFIG[t].icon} {TYPE_CONFIG[t].label}</button>)}
|
|
43
|
-
</div>
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function FeedbackForm({ onSubmit, onClose }: { onSubmit: (data: { type: FeedbackType; title: string; description: string }) => Promise<string>; onClose?: () => void }) {
|
|
48
|
-
const [type, setType] = useState<FeedbackType>('general')
|
|
49
|
-
const [title, setTitle] = useState(''); const [desc, setDesc] = useState('')
|
|
50
|
-
const [submitting, setSubmitting] = useState(false); const [error, setError] = useState<string | null>(null); const [success, setSuccess] = useState(false)
|
|
51
|
-
const submit = async () => {
|
|
52
|
-
if (!title.trim()) { setError('Title required'); return }; if (desc.length < 10) { setError('10+ chars'); return }
|
|
53
|
-
setSubmitting(true); setError(null); try { await onSubmit({ type, title, description: desc }); setSuccess(true) } catch (e) { setError(String(e)) } finally { setSubmitting(false) }
|
|
54
|
-
}
|
|
55
|
-
if (success) return <div className="feedback__success"><div className="feedback__success-icon">🎉</div><div className="feedback__success-text">Thank you!</div><div className="feedback__success-sub">Feedback submitted</div></div>
|
|
56
|
-
return (
|
|
57
|
-
<div className="feedback__form">
|
|
58
|
-
<FeedbackTypeSelector value={type} onChange={setType} />
|
|
59
|
-
<input type="text" className="feedback__form-input" placeholder="Title…" value={title} onChange={e => setTitle(e.target.value)} />
|
|
60
|
-
<textarea className="feedback__form-input feedback__form-textarea" placeholder="Description…" value={desc} onChange={e => setDesc(e.target.value)} />
|
|
61
|
-
{error && <div className="feedback__form-error">{error}</div>}
|
|
62
|
-
<div className="feedback__form-actions">
|
|
63
|
-
{onClose && <button type="button" className="feedback__btn feedback__btn--outline" onClick={onClose}>Cancel</button>}
|
|
64
|
-
<button type="button" className="feedback__btn feedback__btn--primary" onClick={submit} disabled={submitting}>{submitting ? 'Submitting…' : 'Submit'}</button>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function FeedbackWidget({ onSubmit, position = 'right' }: { onSubmit: (data: { type: FeedbackType; title: string; description: string }) => Promise<string>; position?: 'left' | 'right' }) {
|
|
71
|
-
const [isOpen, setIsOpen] = useState(false)
|
|
72
|
-
return (<>
|
|
73
|
-
<button type="button" className="feedback__widget-trigger" onClick={() => setIsOpen(true)}>Feedback</button>
|
|
74
|
-
{isOpen && <div className="feedback__widget-overlay" onClick={() => setIsOpen(false)}>
|
|
75
|
-
<div className="feedback__widget-backdrop" />
|
|
76
|
-
<div className="feedback__widget-panel" onClick={e => e.stopPropagation()}>
|
|
77
|
-
<div className="feedback__widget-header"><span className="feedback__widget-title">Send Feedback</span><button type="button" className="feedback__close-btn" onClick={() => setIsOpen(false)}>✕</button></div>
|
|
78
|
-
<FeedbackForm onSubmit={onSubmit} onClose={() => setIsOpen(false)} />
|
|
79
|
-
</div>
|
|
80
|
-
</div>}
|
|
81
|
-
</>)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function NPSSurvey({ onSubmit, onDismiss }: { onSubmit: (score: number, comment?: string) => void; onDismiss: () => void }) {
|
|
85
|
-
const [score, setScore] = useState<number | null>(null); const [comment, setComment] = useState(''); const [step, setStep] = useState<'score'|'comment'|'thanks'>('score')
|
|
86
|
-
return (
|
|
87
|
-
<div className="feedback__nps">
|
|
88
|
-
{step === 'score' && <div><div className="feedback__nps-header"><span className="feedback__nps-title">How likely to recommend us?</span><button type="button" className="feedback__close-btn" onClick={onDismiss}>✕</button></div><div className="feedback__nps-subtitle">0 = Not at all · 10 = Extremely likely</div>
|
|
89
|
-
<div className="feedback__nps-scores">{Array.from({length:11}).map((_,i) => <button key={i} type="button" className="feedback__nps-score-btn" onClick={() => { setScore(i); setStep('comment') }}>{i}</button>)}</div><div className="feedback__nps-labels"><span>Not likely</span><span>Very likely</span></div></div>}
|
|
90
|
-
{step === 'comment' && <div><div className="feedback__nps-title" style={{marginBottom: '0.75rem'}}>Score: {score}</div><textarea className="feedback__form-input feedback__form-textarea" value={comment} onChange={e => setComment(e.target.value)} placeholder="Optional…" /><button type="button" className="feedback__btn feedback__btn--primary" style={{width:'100%',marginTop:'0.75rem'}} onClick={() => { onSubmit(score!, comment||undefined); setStep('thanks') }}>Submit</button></div>}
|
|
91
|
-
{step === 'thanks' && <div className="feedback__success"><div className="feedback__success-icon">🎉</div><div className="feedback__success-text">Thank you!</div></div>}
|
|
92
|
-
</div>
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export function NPSResults({ responses }: { responses: NPSResponse[] }) {
|
|
97
|
-
const stats = calcNPSStats(responses); const total = stats.totalResponses || 1
|
|
98
|
-
const color = stats.npsScore >= 50 ? 'oklch(0.72 0.18 155)' : stats.npsScore >= 0 ? 'oklch(0.72 0.18 60)' : 'oklch(0.60 0.25 25)'
|
|
99
|
-
return (
|
|
100
|
-
<div className="feedback__nps-results">
|
|
101
|
-
<div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:'0.5rem'}}><span>NPS Score</span><span className="feedback__nps-results-score" style={{color}}>{stats.npsScore}</span></div>
|
|
102
|
-
<div className="feedback__nps-bar"><div className="feedback__nps-bar-detractors" style={{width:`${(stats.detractors/total)*100}%`}} /><div className="feedback__nps-bar-passives" style={{width:`${(stats.passives/total)*100}%`}} /><div className="feedback__nps-bar-promoters" style={{width:`${(stats.promoters/total)*100}%`}} /></div>
|
|
103
|
-
<div className="feedback__nps-breakdown"><div><span style={{color:'oklch(0.60 0.25 25)',fontWeight:700}}>{stats.detractors}</span><br/><span style={{color:'oklch(1 0 0/0.3)'}}>Detractors</span></div><div><span style={{color:'oklch(0.72 0.18 60)',fontWeight:700}}>{stats.passives}</span><br/><span style={{color:'oklch(1 0 0/0.3)'}}>Passives</span></div><div><span style={{color:'oklch(0.72 0.18 155)',fontWeight:700}}>{stats.promoters}</span><br/><span style={{color:'oklch(1 0 0/0.3)'}}>Promoters</span></div></div>
|
|
104
|
-
<div style={{marginTop:'0.75rem',paddingTop:'0.75rem',borderTop:'1px solid oklch(1 0 0/0.05)',display:'flex',justifyContent:'space-between',fontSize:'0.6875rem',color:'oklch(1 0 0/0.4)'}}><span>Avg: {stats.averageScore}/10</span><span>{stats.totalResponses} responses</span></div>
|
|
105
|
-
</div>
|
|
106
|
-
)
|
|
107
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { useFeedback, useFeedbackForm, useNPS, useFeedbackAdmin } from './hooks'
|
|
2
|
-
export type { FeedbackFilter } from './hooks'
|
|
3
|
-
export { StatusBadge, PriorityBadge, TypeBadge, FeedbackCard, FeedbackTypeSelector, FeedbackForm, FeedbackWidget, NPSSurvey, NPSResults } from './components'
|
|
4
|
-
import './styles.css'
|
|
5
|
-
export type { FeedbackItem, NPSResponse, FeedbackConfig, FeedbackStats, NPSStats, FeedbackType, FeedbackStatus, FeedbackPriority } from '@geenius-feedback/shared'
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import '../styles.css';
|
|
3
|
-
|
|
4
|
-
const FeedbackAdminPage: React.FC = () => {
|
|
5
|
-
return (
|
|
6
|
-
<div style={{ padding: '1.5rem' }}>
|
|
7
|
-
<div className="feedback__breadcrumb">
|
|
8
|
-
<span className="feedback__breadcrumb-item">Feedback</span>
|
|
9
|
-
<span className="feedback__breadcrumb-sep">/</span>
|
|
10
|
-
<span className="feedback__breadcrumb-item--active">Admin</span>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
<div className="feedback__stats-grid">
|
|
14
|
-
<div className="feedback__stat-card">
|
|
15
|
-
<div className="feedback__stat-icon">📊</div>
|
|
16
|
-
<div className="feedback__stat-value">7.8</div>
|
|
17
|
-
<div className="feedback__stat-label">NPS Score</div>
|
|
18
|
-
</div>
|
|
19
|
-
<div className="feedback__stat-card">
|
|
20
|
-
<div className="feedback__stat-icon">⭐</div>
|
|
21
|
-
<div className="feedback__stat-value">4.2</div>
|
|
22
|
-
<div className="feedback__stat-label">Avg Rating</div>
|
|
23
|
-
</div>
|
|
24
|
-
<div className="feedback__stat-card">
|
|
25
|
-
<div className="feedback__stat-icon">⏱️</div>
|
|
26
|
-
<div className="feedback__stat-value">2.1h</div>
|
|
27
|
-
<div className="feedback__stat-label">Avg Response</div>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<div className="feedback__filter-panel">
|
|
32
|
-
<div className="feedback__filter-section">
|
|
33
|
-
<div className="feedback__filter-section-title">Status</div>
|
|
34
|
-
<div className="feedback__filter-options">
|
|
35
|
-
<label className="feedback__filter-option">
|
|
36
|
-
<input type="checkbox" defaultChecked />
|
|
37
|
-
<span className="feedback__filter-option-label">Open</span>
|
|
38
|
-
</label>
|
|
39
|
-
<label className="feedback__filter-option">
|
|
40
|
-
<input type="checkbox" defaultChecked />
|
|
41
|
-
<span className="feedback__filter-option-label">Under Review</span>
|
|
42
|
-
</label>
|
|
43
|
-
<label className="feedback__filter-option">
|
|
44
|
-
<input type="checkbox" defaultChecked />
|
|
45
|
-
<span className="feedback__filter-option-label">Planned</span>
|
|
46
|
-
</label>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
<div className="feedback__filter-section">
|
|
50
|
-
<div className="feedback__filter-section-title">Priority</div>
|
|
51
|
-
<div className="feedback__filter-options">
|
|
52
|
-
<label className="feedback__filter-option">
|
|
53
|
-
<input type="checkbox" defaultChecked />
|
|
54
|
-
<span className="feedback__filter-option-label">Critical</span>
|
|
55
|
-
</label>
|
|
56
|
-
<label className="feedback__filter-option">
|
|
57
|
-
<input type="checkbox" defaultChecked />
|
|
58
|
-
<span className="feedback__filter-option-label">High</span>
|
|
59
|
-
</label>
|
|
60
|
-
<label className="feedback__filter-option">
|
|
61
|
-
<input type="checkbox" />
|
|
62
|
-
<span className="feedback__filter-option-label">Low</span>
|
|
63
|
-
</label>
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
|
|
68
|
-
<div style={{ marginTop: '2rem' }}>
|
|
69
|
-
<h3 style={{ fontSize: '0.875rem', fontWeight: '600', marginBottom: '1rem', color: 'oklch(1 0 0 / 0.8)' }}>
|
|
70
|
-
Recent Activity
|
|
71
|
-
</h3>
|
|
72
|
-
<table className="feedback__admin-table">
|
|
73
|
-
<thead>
|
|
74
|
-
<tr>
|
|
75
|
-
<th>Item</th>
|
|
76
|
-
<th>Status</th>
|
|
77
|
-
<th>Priority</th>
|
|
78
|
-
<th>Votes</th>
|
|
79
|
-
</tr>
|
|
80
|
-
</thead>
|
|
81
|
-
<tbody>
|
|
82
|
-
<tr>
|
|
83
|
-
<td>Add Dark Mode</td>
|
|
84
|
-
<td>
|
|
85
|
-
<select className="feedback__admin-select">
|
|
86
|
-
<option>In Progress</option>
|
|
87
|
-
<option>Planned</option>
|
|
88
|
-
<option>Open</option>
|
|
89
|
-
</select>
|
|
90
|
-
</td>
|
|
91
|
-
<td>High</td>
|
|
92
|
-
<td>42</td>
|
|
93
|
-
</tr>
|
|
94
|
-
<tr>
|
|
95
|
-
<td>Login Timeout Issue</td>
|
|
96
|
-
<td>
|
|
97
|
-
<select className="feedback__admin-select">
|
|
98
|
-
<option>Open</option>
|
|
99
|
-
<option>In Progress</option>
|
|
100
|
-
</select>
|
|
101
|
-
</td>
|
|
102
|
-
<td>Critical</td>
|
|
103
|
-
<td>12</td>
|
|
104
|
-
</tr>
|
|
105
|
-
</tbody>
|
|
106
|
-
</table>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
);
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
export default FeedbackAdminPage;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import '../styles.css';
|
|
3
|
-
|
|
4
|
-
const FeedbackPage: React.FC = () => {
|
|
5
|
-
const feedbackItems = [
|
|
6
|
-
{ id: 1, title: 'Add Dark Mode', type: 'feature', status: 'in-progress', votes: 42, priority: 'high' },
|
|
7
|
-
{ id: 2, title: 'Bug: Login timeout issue', type: 'bug', status: 'open', votes: 12, priority: 'critical' },
|
|
8
|
-
{ id: 3, title: 'Improve API documentation', type: 'suggestion', status: 'planned', votes: 28, priority: 'medium' },
|
|
9
|
-
];
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<div style={{ padding: '1.5rem' }}>
|
|
13
|
-
<div className="feedback__breadcrumb">
|
|
14
|
-
<span className="feedback__breadcrumb-item">Feedback</span>
|
|
15
|
-
<span className="feedback__breadcrumb-sep">/</span>
|
|
16
|
-
<span className="feedback__breadcrumb-item--active">View All</span>
|
|
17
|
-
</div>
|
|
18
|
-
|
|
19
|
-
<div className="feedback__stats-grid">
|
|
20
|
-
<div className="feedback__stat-card">
|
|
21
|
-
<div className="feedback__stat-icon">💬</div>
|
|
22
|
-
<div className="feedback__stat-value">145</div>
|
|
23
|
-
<div className="feedback__stat-label">Total Feedback</div>
|
|
24
|
-
</div>
|
|
25
|
-
<div className="feedback__stat-card">
|
|
26
|
-
<div className="feedback__stat-icon">👍</div>
|
|
27
|
-
<div className="feedback__stat-value">89</div>
|
|
28
|
-
<div className="feedback__stat-label">In Progress</div>
|
|
29
|
-
</div>
|
|
30
|
-
<div className="feedback__stat-card">
|
|
31
|
-
<div className="feedback__stat-icon">✅</div>
|
|
32
|
-
<div className="feedback__stat-value">34</div>
|
|
33
|
-
<div className="feedback__stat-label">Implemented</div>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
|
|
37
|
-
<div className="feedback__filter-tabs" style={{ marginBottom: '1.5rem' }}>
|
|
38
|
-
<button className="feedback__filter-tab feedback__filter-tab--active">All</button>
|
|
39
|
-
<button className="feedback__filter-tab feedback__filter-tab--inactive">Features</button>
|
|
40
|
-
<button className="feedback__filter-tab feedback__filter-tab--inactive">Bugs</button>
|
|
41
|
-
<button className="feedback__filter-tab feedback__filter-tab--inactive">Suggestions</button>
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
|
|
45
|
-
{feedbackItems.map(item => (
|
|
46
|
-
<div key={item.id} className={`feedback__card feedback__card--${item.type}`}>
|
|
47
|
-
<div className="feedback__vote-btn feedback__vote-btn--inactive">
|
|
48
|
-
<span className="feedback__vote-btn-arrow">▲</span>
|
|
49
|
-
<span>{item.votes}</span>
|
|
50
|
-
</div>
|
|
51
|
-
<div className="feedback__card-info">
|
|
52
|
-
<div className="feedback__card-badges">
|
|
53
|
-
<span className={`feedback__type-badge feedback__type-badge--${item.type}`}>{item.type}</span>
|
|
54
|
-
<span className={`feedback__status-badge feedback__status-badge--${item.status}`}>{item.status}</span>
|
|
55
|
-
<span className="feedback__priority-badge feedback__priority-badge--high">{item.priority}</span>
|
|
56
|
-
</div>
|
|
57
|
-
<div className="feedback__card-title">{item.title}</div>
|
|
58
|
-
<div className="feedback__card-meta">
|
|
59
|
-
<span>Posted by user</span>
|
|
60
|
-
<span>2 days ago</span>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
))}
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
<div className="feedback__pagination">
|
|
68
|
-
<button className="feedback__pagination-btn">Previous</button>
|
|
69
|
-
<span className="feedback__pagination-info">Page 1 of 5</span>
|
|
70
|
-
<button className="feedback__pagination-btn">Next</button>
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export default FeedbackPage;
|